Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在不调用QApplication::exec()的情况下,显示小部件的正确方法是什么?_C++_Qt - Fatal编程技术网

C++ 在不调用QApplication::exec()的情况下,显示小部件的正确方法是什么?

C++ 在不调用QApplication::exec()的情况下,显示小部件的正确方法是什么?,c++,qt,C++,Qt,出于测试目的,我想创建并显示一个小部件。现在我只需要小部件正确渲染,但将来我可能希望扩展它,以便模拟各种事件来查看小部件的行为 从各种来源来看,似乎应采取以下措施: QApplication app; QPushButton button("Hello"); button.show(); // Might also be necessary: QApplication::processEvents(); 但对我来说,小部件不能正确呈现。创建一个窗口来显示小部件,但是它是

出于测试目的,我想创建并显示一个小部件。现在我只需要小部件正确渲染,但将来我可能希望扩展它,以便模拟各种事件来查看小部件的行为

从各种来源来看,似乎应采取以下措施:

QApplication app;

QPushButton button("Hello");
button.show();

// Might also be necessary:
QApplication::processEvents();
但对我来说,小部件不能正确呈现。创建一个窗口来显示小部件,但是它是完全黑色的

我可以通过添加以下行使小部件正确呈现:

std::this_thread::sleep_for(std::chrono::milliseconds(10));
QApplication::processEvents();
10毫秒是使小部件正确渲染所需的最短时间


是否有人知道如何在没有时间延迟的情况下使其工作,或者知道为什么需要延迟?

为什么不让应用程序运行exec?显示小部件的过程不是“静态”的。您没有在屏幕上“绘制”小部件,而是有一个应用程序,它可以侦听各种事件并从窗口管理器接收绘制事件。应用程序只能在窗口管理器要求时绘制小部件

第二个代码工作的原因是您等待窗口管理器在您的条件下发送“绘制”请求的时间足够长。这并不能保证它总是有效的


如果你想保证小部件的显示,你需要开始一个循环,直到你收到至少一个平局事件,但即使这样也不是万无一失的。

正如文森特·福蒙德(Vincent Fourmond)熟练地描述的那样,小部件不是一次性交易。GUI是非阻塞的,为此,它需要在事件循环中运行

exec()
方法启动您通过轮询模拟的事件循环。 虽然可以将Qt的事件循环与其他事件循环相结合,但我建议您使用一种更简单的解决方案:

在事件循环中,通过在程序启动时调用一个方法来继续程序。在此处找到一个关于如何执行此操作的极好答案:


正如您提到的单元测试,还有一个信号可以用于在生命周期结束时(小部件被销毁之前)进行检查:
QApplication::aboutToQuit
。当最后一个窗口关闭时(通过编程或由用户关闭)会发生这种情况。

要测试Qt GUI应用程序,您至少需要处理
QApplication
实例和事件循环。最快的方法就是使用
QTEST_MAIN
macro,以一种很好的方式解释它的确切功能。但是,为了具有更大的灵活性(例如,使用GTest、GMock),您也可以简单地在tests main中创建
qApplication
实例(无需调用
exec

然后,要处理事件,您应该调用。这将在指定的时间内处理事件。使用接受谓词的
qWaitFor
是一种很好的做法,这样可以避免测试中的竞争条件

在特定场景中,当您希望发出某些信号时,也可以使用的类似功能

当我们想等待一些参数从一个项目传递到另一个项目时,举个小例子:

QSignalSpy spy(&widget1, &Widget1::settingsChanged);
widget2->applySettings();
ASSERT_TRUE(spy.wait(5000));
// do some further tests based on the content of passed settings

原因是exec阻塞。这在测试场景中是有问题的,在测试场景中,理想情况下您希望执行以下操作:创建、显示、模拟条件、检查条件,然后退出。如果调用exec,那么如何手动创建事件,例如QTest库()中的事件?然后可以使用连接到QApplication::quit()的计时器插槽。然后在指定的时间后终止应用程序@User975326如何将GUI移动到不同的线程?我不确定这是否适用于Qt应用程序。我看到第二个选项会起作用,只是有点不幸,它需要一点锅炉板,不太符合我希望单元测试阅读的线性方式。但是如果没有办法上班,这是一个很好的选择。谢谢。我只是想回答你关于线程的问题。Qt具有QoObject的“线程关联性”,并且根据对象与其关联的线程,它将在该线程中处理信号。Qt有一个重要的必要条件,即任何与GUI相关的对象(例如,QWidgets)都在单个线程中运行。我认为这不一定是主线程,但当前文档说“GUI类,尤其是QWidget[…]只能从主线程使用。[…]QCoreApplication::exec()也必须从该线程调用。”因此我收回了该选项。QTest::qWait。我想这就是我要找的东西!