QWidget 失去了它的父级
Posted
技术标签:
【中文标题】QWidget 失去了它的父级【英文标题】:QWidget loses its parent 【发布时间】:2016-09-22 10:19:13 【问题描述】:在我的应用程序中,我有一个QDialog
,它本身包含一个复杂的、QWidget
派生的 GUI 元素。 QDialog
是模态的,使用 exec()
打开,嵌入式 GUI 元素处理所有用户交互。
所以只有QWidget
这个孩子知道QDialog
什么时候可以关闭,这样做是这样的:
QDialog* parent=qobject_cast<QDialog*>(parentWidget());
if (parent) parent->close();
这是必要的,因为QDialog
必须关闭,而不仅仅是QWidget
。
现在用户报告了QDialog::exec()
已返回但对话框(或仅 GUI 元素?)仍然可见的情况。从日志文件中我可以看到QDialog::exec()
确实已经返回,并且该调用执行后的代码。
所以我目前的假设是:GUI 元素已经失去了它的父元素,因此上面显示的 close()
调用没有被调用,因为“父元素”为空。
知道这是怎么发生的吗? QWidget
的父级是否可以通过常规方式消失?
【问题讨论】:
您是否有充分的理由不将您孩子的信号连接到对话框的accept()
或reject()
插槽?
@thuga 我这里无法重现这个问题,所以这个评论完全没用
那么把它写在问题里。
@thuga 已经提到了一句“现在用户报告了一个情况......”
所以用户报告的任何内容都自动意味着它不能被复制?无论如何,QDialog::exec
仅在对话框隐藏(或关闭)时返回。你能告诉我们对话框是否有可能被创建了两次?
【参考方案1】:
一般来说,使用QDialog::exec
重新进入事件循环会带来麻烦,因为突然间所有在主线程中运行的代码都必须是可重入的。你很可能正面临着由此产生的后果。不要重新进入事件循环,你会没事的,否则问题会重现。
如果您需要对被接受或拒绝的对话框做出反应,请将代码连接到相关插槽。 IE。改变这个:
void do()
MyDialog dialogthis;
auto rc = dialog.exec();
qDebug() << "dialog returned" << rc;
到那个:
class Foo : public QWidget
MyDialog dialogthis;
...
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 MyDialogthis;
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 layoutthis;
MyWidget widget;
public:
MyDialog()
layout.addWidget(&widget, 0, 0);
connect(&widget, &MyWidget::isDone, this, &QDialog::accepted);
;
【讨论】:
我很惊讶文档中没有提到它,如果可能的话,应该避免嵌套事件循环,例如QDialog::exec
。在一些博客中提到过,但我认为应该更明显。以上是关于QWidget 失去了它的父级的主要内容,如果未能解决你的问题,请参考以下文章
qwidget.setGeometry() 在 linux 上的位置不正确