【发布时间】:2014-08-08 02:03:14
【问题描述】:
我想 exec() 一个没有 GUI 的 QDialog 用于我的测试 - 不需要显示 GUI。
在主窗口中,当我 exec() 一个 QDialog 时,它会显示它的 GUI 窗口。我将来自 QDialog 中线程的信号连接到 QDialog 中的插槽,因此需要 QDialog.exec()。 QDialog.hide() 不起作用。
有什么解决办法吗?
【问题讨论】:
标签: qt
我想 exec() 一个没有 GUI 的 QDialog 用于我的测试 - 不需要显示 GUI。
在主窗口中,当我 exec() 一个 QDialog 时,它会显示它的 GUI 窗口。我将来自 QDialog 中线程的信号连接到 QDialog 中的插槽,因此需要 QDialog.exec()。 QDialog.hide() 不起作用。
有什么解决办法吗?
【问题讨论】:
标签: qt
你永远不应该exec() 对话。这可能会导致细微的错误,因为exec() 调用可以重新输入您不打算重新输入的代码。
如果你真的坚持使用exec(),那么简单的解决方案是在对话框中发布CloseEvent。一旦对话框的事件循环开始运行,就会处理该事件。
MyDialog dialog;
QCoreApplication::postEvent(&dialog, new QCloseEvent());
dialog.exec();
此代码在功能上等同于以下代码:
MyDialog dialog;
QMetaObject::invokeMethod(&dialog, "close", Qt::QueuedConnection);
dialog.exec();
另一种更安全的方法是不使用exec。只需将对话框的 accepted() 和 rejected() 信号连接到代码中的槽 - 毕竟,对话框的接受或拒绝是异步发生的。
这样就很容易了,只需不在测试代码路径中show() 对话框。您还可以通过调用accept 或reject 插槽轻松模拟被接受或拒绝的对话框。
我真的不明白您是如何将信号从线程“连接”到对话框的插槽等的。随意将下面的示例粘贴到您的问题中,修改它以执行线程化的“东西”,并展示它是如何不起作用的。了解您是如何实现测试工具的也会有所帮助。
下面的示例都是一个文件,如果您在生成说明您的问题的测试用例时保持这种方式会有所帮助。
// main.cpp
#include <QApplication>
#include <QDialog>
#include <QLabel>
#include <QGridLayout>
#include <QPushButton>
#include <QDialogButtonBox>
class MyDialog : public QDialog {
QGridLayout m_layout;
QDialogButtonBox m_box;
public:
MyDialog(QWidget * parent = 0) : QDialog(parent), m_layout(this),
m_box(QDialogButtonBox::Ok | QDialogButtonBox::Cancel)
{
m_layout.addWidget(&m_box);
connect(&m_box, SIGNAL(accepted()), SLOT(accept()));
connect(&m_box, SIGNAL(rejected()), SLOT(reject()));
}
};
class MyGui : public QWidget {
Q_OBJECT
QGridLayout m_layout;
QLabel m_label;
QPushButton m_button;
MyDialog m_dialog;
Q_SLOT void on_button_clicked() {
m_dialog.show();
}
Q_SLOT void on_dialog_accepted() {
m_label.setText("The dialog was accepted");
}
Q_SLOT void on_dialog_rejected() {
m_label.setText("The dialog was rejected");
}
public:
MyGui() : m_layout(this), m_button("Show Dialog"), m_dialog(this) {
m_button.setObjectName("button");
m_dialog.setObjectName("dialog");
m_layout.addWidget(&m_label);
m_layout.addWidget(&m_button);
QMetaObject::connectSlotsByName(this);
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyGui gui;
gui.show();
return app.exec();
}
#include "main.moc"
【讨论】:
QWidget 或QPixmap 方法。您可以使用QMetaObject::invokeMethod(widget, "method", Qt::QueuedConnection) 安全地对可调用方法进行跨线程调用。