如果设置了父级,QDialog::show()
不会显示窗口是预期行为吗?
背景:我想使用QMetaObject::connectSlotsByName()
对其中一个对话框信号做出反应,这意味着父对象需要拥有它。没有标记为“ 这是相关行”的行,我得到一个运行时消息“ QMetaObject :: connectSlotsByName:on_child_accepted()无匹配信号”。但是有了这一行,子对话框将不再出现。
#include <QtCore/QDebug>
#include <QtWidgets/QApplication>
#include <QtWidgets/QDialog>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QVBoxLayout>
class Parent : public QDialog
{
Q_OBJECT
public:
Parent(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags())
: QDialog{parent, f}
{
b.setText(tr("Show child"));
connect(&b, &QPushButton::clicked, [&]() {
c.show();
});
l.addWidget(&b);
setLayout(&l);
c.setParent(this); // This is the line in question
c.setObjectName("child");
QMetaObject::connectSlotsByName(this);
}
private slots:
void on_child_accepted()
{
qDebug() << "I got called";
}
private:
QPushButton b;
QDialog c;
QVBoxLayout l;
};
#include "main.moc"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Parent w;
w.show();
return a.exec();
}
此测试在Windows的Qt 5.11上通过MSYS2 64位版本失败。
有什么建议吗?预先谢谢你。
答案 0 :(得分:1)
该对话框实际上确实出现了,但是却没有显示出来:它是窗口的非窗口子窗口小部件-它是透明的,但是却遮盖了大部分“显示对话框”按钮,消耗了所有鼠标事件,而且已经显示了,因为所有的孩子都在显示父对象时显示了-因此,由于这两个原因,该按钮似乎无法正常工作。
设置小部件的父级将清除其Qt::Window
标志。设置对话框的背景有助于可视化问题。因此,您需要在设置对话框的父级后将其设置为窗口。
以下内容重现了您的错误,并演示了解决方法。
// https://github.com/KubaO/stackoverflown/tree/master/questions/dialog-show-parenting-53208641
#include <QtWidgets>
class Parent : public QDialog {
Q_OBJECT
QVBoxLayout layout{this};
QDialog child;
QPushButton cShow{tr("Show child")}, cNonWindow{tr("Renew non-window child")},
cWindow{tr("Renew window child")};
Q_SLOT void on_child_accepted() {}
void reChild(bool makeWindow) {
child.~QDialog();
new (&child) QDialog;
Q_ASSERT(child.isWindow());
child.setParent(this);
child.setObjectName("child");
child.setStyleSheet("QWidget { background: blue }");
if (makeWindow) {
child.setWindowFlag(Qt::Dialog);
Q_ASSERT(child.isWindow());
} else {
Q_ASSERT(!child.isWindow());
child.show(); // The child gets shown when we're shown
}
QMetaObject::invokeMethod(this, &Parent::updateChild, Qt::QueuedConnection);
}
void updateChild() {
if (!child.isWindow()) child.move(50, cWindow.y() + cWindow.height() / 2);
this->update(); // Work around a refresh bug (affects OS X on 5.11 at least)
}
public:
Parent(QWidget *parent = nullptr, Qt::WindowFlags f = {}) : QDialog{parent, f} {
connect(&cShow, &QPushButton::clicked, [&]() { child.show(); });
connect(&cNonWindow, &QPushButton::clicked, [&] { reChild(false); });
connect(&cWindow, &QPushButton::clicked, [&] { reChild(true); });
for (auto *w : {&cShow, &cNonWindow, &cWindow}) layout.addWidget(w);
cNonWindow.click();
QMetaObject::connectSlotsByName(this);
}
};
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
Parent w;
w.show();
return a.exec();
}
#include "main.moc"