【问题标题】:Showing the same QPushButton on multiple widgets在多个小部件上显示相同的 QPushButton
【发布时间】:2011-08-12 15:52:39
【问题描述】:

我有两个小部件(真实的和假的),其中一个有一个 QPushButton。现在我希望在另一个小部件中显示相同的按钮。我该怎么做?

我不想创建副本,我希望在不更改父级的情况下同时显示同一个 QObject 上的另一个小部件。

例如,在下面我希望“mybutton”同时显示在两个小部件中;

  QWidget *widgetReal = new QWidget();
  QWidget *widgetFake = new QWidget();
  widgetReal->setWindowTitle("Real");
  widgetFake->setWindowTitle("Fake");
  widgetReal->show();
  widgetFake->show();

  QGridLayout *layoutReal = new QGridLayout();
  QGridLayout *layoutFake = new QGridLayout();

  QPushButton *mybutton = new QPushButton();

  layoutReal->addWidget(mybutton);
  widgetReal->setLayout(layoutReal);

  layoutFake->addWidget(mybutton); //this changes the parent and this is not what I want to do
  widgetFake->setLayout(layoutFake);

  mybutton->show();

我需要这个的原因是因为我有一堆 MDISubWindows,它们包含一些控件(按钮、复选框......等)。现在我想从这些小部件中选择其中一些控件并创建一个小部件。这样做的原因是,当我只使用一个按钮时,我不想显示我的所有 MDISubwindow 任何建议都非常有帮助。谢谢。

-简历

【问题讨论】:

  • 为什么需要这个?你想完成什么?
  • 我编辑了回答您评论的问题

标签: qt layout copy qobject


【解决方案1】:

QWidgets 应该只有一个父级。毫无疑问,您可以想出一些技巧来大致实现您想要的,但是当您可以重新设计以适应 Qt GUI 系统的工作方式时,为什么还要这样做呢?

不要试图与框架作斗争。如果你这样做了,你最终会得到难以理解和难以维护的代码。

【讨论】:

  • 我明白这一点。但是如果我们从不同的角度来看按钮元素的设计,“按钮对象”是否应该与其外观分开,即一个按钮对象可以出现在很多地方。
【解决方案2】:

Qt 不支持你想做的,所以我会引用stu's response:

不要试图与框架作斗争。如果你这样做了,你最终会得到难以理解和难以维护的代码。

虽然一个小部件不能同时出现在多个位置,但您可以让它看起来像这样:

void MyWidget::paintEvent(QPaintEvent *e) {
    QPainter p(this);
    QWidget *w = getRepeatableWidget();
    w->render(this, getPosition1());
    w->render(this, getPosition2());
}

完成此操作后,您将需要处理任何点击和其他事件,并使其显示为已转发等,但除非您付出很多努力,否则您将失去焦点提示和其他内容.

【讨论】:

    【解决方案3】:

    不要认为你可以;一个小部件一次只有一个父级。您可以使用 setParent() 移动它,但不能让它同时显示在多个父级中。

    【讨论】:

    • 我可能最终只是这样做,但即使在这种情况下,它也可能使我的代码变得混乱,因为有时我评估孩子并连接然后使用 SignalMapper。
    【解决方案4】:

    您可以创建 QActions 并将它们嵌入到多个 QToolButton(使用 QToolButton::setDefaultAction)或通过将操作添加到 QToolBar 中,而不是尝试在多个父级之间共享一个按钮。

    QAction 可以是可检查/可切换的,并且可以添加到独占组 (QActionGroup) 以具有与单选按钮相同的行为。 所有 QToolButtons 属性和状态都将与它们链接到的 QAction 中的属性和状态保持同步。

    【讨论】:

    • 好吧,现在这是一种变通方法,仅适用于某些特定情况。如果我想要一个完整的重复小部件(但不是副本),那么这是行不通的。我的意思是,我们可以破解它,但这会违反大部分规则并使代码更难理解:D
    【解决方案5】:

    无论如何,我为此设计了一个技巧。我想要做的是将外观与实际按钮对象分开。这是一个示例代码,需要扩展以获得更多功能

    文件:: VirtualQPushButton.h

    #ifndef VIRTUALQPUSHBUTTON_H
    #define VIRTUALQPUSHBUTTON_H
    #include <QPushButton>
    //! \class Class that forwards signals to the base button
    class VirtualQPushButton : public QPushButton
    {
      Q_OBJECT
    public:
      VirtualQPushButton (QPushButton &basebutton, QWidget * parent = 0) :
        QPushButton (parent),
        m_button (&basebutton)
      {
        QObject::connect(this, SIGNAL(clicked()), this, SLOT(forwardClick()));
        //don't forget to forward other signals too
      }
    
    protected slots:
      void forwardClick()
      {
        if (m_button)
        {
          m_button->click();
        }
      }
    
    private:
      QPushButton *m_button;
    };
    #endif // VIRTUALQPUSHBUTTON_H
    

    文件:: main.cpp

    #include <QtGui/QApplication>
    #include <QHBoxLayout>
    #include "VirtualQPushButton.h"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QWidget w;
    
        QPushButton *basebutton = new QPushButton (&w);
        basebutton->hide();
        QObject::connect (basebutton, SIGNAL (clicked()), &w, SLOT (close()));
    
        VirtualQPushButton *buton1 = new VirtualQPushButton (*basebutton);
        buton1->setText("Buton1");
        VirtualQPushButton *buton2 = new VirtualQPushButton (*basebutton);
        buton2->setText("Buton2");
    
        QHBoxLayout *lyt = new QHBoxLayout();
        lyt->addWidget(buton1);
        lyt->addWidget(buton2);
        w.setLayout(lyt);
        w.show();
    
        return a.exec();
    }
    

    让我知道您的意见,感谢您的所有回复。

    简历

    【讨论】:

    • 如果我想要两个由 Qt Designer 创建和提升的按钮,我该怎么做?如果我使用静态实例,我会收到错误,因为小部件期望应用程序之前运行。我没有机会在promote中使用构造函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-15
    • 1970-01-01
    • 2017-03-23
    • 2018-09-26
    • 2019-12-10
    • 1970-01-01
    相关资源
    最近更新 更多