简体   繁体   English

Xlib:从同一Qt应用程序中的单独QThread测试Qt应用程序时出现意外的异步回复

[英]Xlib: unexpected async reply when testing Qt application from a separate QThread within same Qt application

I am trying to create a test for my Qt appication. 我正在尝试为我的Qt应用创建测试。 The aim is to test the GUI of the application by moving the mouse around and clicking on QGraphicsItems or QWidgets using the X11 library. 目的是通过移动鼠标并使用X11库单击QGraphicsItems或QWidgets来测试应用程序的GUI。

The test is written as a plugin for my Qt application. 该测试是作为Qt应用程序的插件编写的。 It launches a separate QThread and in the run() function I do the mouse moving. 它启动一个单独的QThread,然后在run()函数中移动鼠标。 Lets call this the 'test running thread' 让我们称其为“测试运行线程”

However I also need to get the structure of the GUI ie the location of various widgets, so in the 'test running thread' I go through the QApplication::topLevelWidgets() and find the one I am interested in. Then I call mapToGlobal() on this widget to gets its global position. 但是,我还需要获取GUI的结构,即各种小部件的位置,因此在“测试运行线程”中,我遍历QApplication :: topLevelWidgets()并找到了我感兴趣的那个。然后我将mapToGlobal( )在此小部件上以获取其全球位置。 This position can then be fed to the X11 mouse functions to move the mouse over the widget. 然后可以将此位置输入X11鼠标功能,以将鼠标移到小部件上。

This works generally but once in a while I get this error 'Xlib: unexpected async reply' Some googling revealed that this can be due to setting QWidget positions or trying to update them from another thread. 这通常可以正常工作,但偶尔我会收到此错误“ Xlib:意外的异步回复”。一些谷歌搜索发现这可能是由于设置了QWidget位置或试图从另一个线程更新它们。

But I simply get information about widgets in another thread. 但是我只是在另一个线程中获得有关小部件的信息。 Why would that cause a problem ? 为什么会引起问题? :( :(

If all else fails, I am prepared to setup some kind of communication queue back to the main(GUI) thread. 如果所有其他方法都失败了,我准备将某种通信队列设置回主(GUI)线程。 The 'test running thread' will place requests for information about widgets on the queue and the GUI thread can respond to them. “测试运行线程”将请求有关小部件的信息的请求放在队列上,GUI线程可以响应它们。

The reason why the plugin launches a separate thread to move the mouse is because the GUI must continue to respond to events otherwise the entire point of the exercise is lost. 插件启动单独的线程来移动鼠标的原因是因为GUI必须继续响应事件,否则整个练习都将丢失。 I know that I could also not use a thread, and simply move the mouse in the main thread calling processEvents() regularly. 我知道我也不能使用线程,只需定期调用processEvents() 的主线程中移动鼠标即可。 Thats the other option I have I guess. 那就是我猜的另一个选择。

Any ideas from someone who has been down this route before would be very helpful. 曾经走过这条路的人的任何想法都会很有帮助。 Thanks ! 谢谢 !

But I simply get information about widgets in another thread. 但是我只是在另一个线程中获得有关小部件的信息。 Why would that cause a problem ? 为什么会引起问题? :( :(

Because you are still sending X protocol messages back and forth. 因为您仍在来回发送X协议消息。 toGlobal() is sure to query the X server about the actual position of the widget (since it may have been moved by some other mean). toGlobal()一定要向X服务器查询小部件的实际位置(因为它可能已经以其他方式移动了)。 So unfortunately, 'just getting some information' is not a const operation as far as X is concerned. 因此,就X而言,不幸的是,“仅获取某些信息”并不是const操作。 Actually, moving your mouse from the test thread is a big no-no as well for the same reason. 实际上,出于同样的原因,将鼠标从测试线程移开也是很大的禁忌。

In your case, I would simply use a zero-timeout QTimer/processEvents and forget about the thread; 在您的情况下,我将仅使用零超时QTimer / processEvents并忽略线程。 it's not worth the trouble of setting up queues to move events back and forth, not to mention you need to add mutexes (!) to your code. 设置队列来回移动事件是不值得的,更不用说您需要在代码中添加互斥体(!)了。

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

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