繁体   English   中英

QWidget失去了父母

[英]QWidget loses its parent

在我的应用程序中,我有一个QDialog ,它本身包含一个复杂的QWidget派生的GUI元素。 QDialog是模态的,并使用exec()打开,并且嵌入式GUI元素处理所有用户交互。

因此只有这个子QWidget知道何时可以关闭QDialog ,这是通过以下方式完成的:

QDialog* parent=qobject_cast<QDialog*>(parentWidget());
if (parent) parent->close();

这是必需的,因为不仅必须关闭QWidget而且必须关闭QDialog

现在,用户报告了QDialog::exec()已返回但对话框(或仅GUI元素?)仍然可见的情况。 从日志文件中,我可以看到QDialog::exec()确实已经返回,并且此调用执行后立即执行了代码。

因此,我目前的假设是:GUI元素丢失了其父元素,因此未调用上面显示的close()调用,因为“ parent”为null。

知道如何发生吗? QWidget的父级是否可以通过常规方式消失?

一般来说,使用QDialog::exec重新进入事件循环会造成麻烦,因为突然之间,在主线程中运行的所有代码都必须重新进入。 很可能您会因此而面临后果。 不要重新进入事件循环,这样就可以了,否则问题将变得可重现。

如果您需要对对话框被接受或拒绝做出反应,请将代码连接到相关插槽。 即更改此:

void do() {
  MyDialog dialog{this};
  auto rc = dialog.exec();
  qDebug() << "dialog returned" << rc;
}

对此:

class Foo : public QWidget {
  MyDialog dialog{this};
  ...
  Foo() {
    connect(&dialog, &QDialog::done, this, &Foo::dialogDone);
  }
  void do() {
    dialog.show();
  }
  void dialogDone(int rc) {
    qDebug() << "dialog returned" << rc;
  }
};

或者,如果您想延迟初始化对话框:

class Foo : public QWidget {
  MyDialog * m_dialog = nullptr;
  MyDialog * dialog() {
    if (! m_dialog) {
      m_dialog = new MyDialog{this};
      connect(m_dialog, &QDialog::done, this, &Foo::dialogDone);
    }
    return m_dialog;
  }
  ...
  void do() {
    dialog()->show();
  }
  void dialogDone(int rc) {
    qDebug() << "dialog returned" << rc;
  }
};

子控件试图与父控件进行干涉是一种可怕的反模式。 小部件具有父级的知识不应泄漏到小部件中,而应将其本地化为父级。 因此,子窗口小部件应发出指示例如数据已被接受的信号。 创建对话框时,将此信号连接到对话框的accept()close()插槽:

class MyWidget : public QWidget {
  Q_OBJECT
public:
  Q_SIGNAL void isDone();
  ...
};

class MyDialog : public QDialog {
  QGridLayout layout{this};
  MyWidget widget;
public:
  MyDialog() {
    layout.addWidget(&widget, 0, 0);
    connect(&widget, &MyWidget::isDone, this, &QDialog::accepted);
  }
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM