I'm new to Qt, but need to solve a difficult problem.
我刚到Qt,但需要解决一个难题。
I've created a VERY simple GUI that I need to add to an existing C++ application. The problem is, I'm writing just one module that plugs into a larger architecture which restricts my access to the main thread.
我创建了一个非常简单的GUI,需要添加到现有的c++应用程序中。问题是,我只编写了一个模块,它插入了一个更大的架构,这限制了我对主线程的访问。
My code must reside inside the four following functions: an Init() function, which runs in the main thread. and WorkerStart(), WorkerStep(), and WorkerStop() functions that run in a worker thread.
我的代码必须驻留在以下四个函数中:Init()函数,它在主线程中运行。和WorkerStart()、WorkerStep()和WorkerStop()函数在工作线程中运行。
I coded my QApplication and GUI objects in the Init() function. But of course, calling app.exec() at the end of that function blocks the entire rest of the code. Not workable.
我在Init()函数中编写了我的QApplication和GUI对象。当然,在函数的末尾调用app.exec()会阻塞整个代码。不可行。
Everything I'm reading says that Qt gui objects can only run in the main thread.
我读的所有内容都说明Qt gui对象只能在主线程中运行。
So my question is, how can I set up my gui in the init() function (main thread) and allow it to run by only using the worker thread from then on?
因此,我的问题是,如何在init()函数(主线程)中设置我的gui,并允许它仅通过使用工作线程来运行?
I found this: QApplication In Non-Main Thread
我发现了这个:QApplication在非主线程中。
and those solutions gave me some different behavior. In the right direction, but not stable or fully functional. But I dont understand why those are solutions at all if qt gui's can only run in main thread, and these solutions put them in other threads. So thats sending mixed messages on what can and can not run in other threads, and it becomes very confusing.
这些解决方案给了我一些不同的行为。在正确的方向上,但不稳定或功能齐全。但是我不明白为什么这些都是解决方案,如果qt gui只能在主线程中运行,这些解决方案将它们放到其他线程中。所以,这就是在其他线程中发送和不能运行的混合消息,这变得非常混乱。
It seems that adding a gui to an existing C++ program without locking it up in the exec() func should be a fairly common situation so I feel like I'm missing something obvious. Can someone help with how I can solve this?
似乎在现有的c++程序中添加一个gui而不将其锁定在exec() func中应该是一个相当普遍的情况,所以我觉得我遗漏了一些明显的东西。有人能帮我解决这个问题吗?
Much thanks in advance. Phil
提前谢谢。菲尔。
1 个解决方案
#1
20
Most of the time, "main thread" == "GUI thread", so people use those terms interchangeably -- even the official documentation does that. I agree that it's confusing though, because they don't have to be the same.^ The actual rule is this:
大多数时候,“主线程”=“GUI线程”,所以人们可以互换使用这些术语——甚至官方文档也会这样做。我同意这是令人困惑的,因为它们不一定是相同的。^实际的规则是这样的:
GUI classes must only be accessed from the thread which instantiates
QApplication
/QGuiApplication
只能从实例化QApplication/QGuiApplication的线程访问GUI类。
With a plugin like yours, here is what you need to do:
有了像你这样的插件,以下是你需要做的:
- Create a new
std::thread
(NOT aQThread
) - 创建一个新的std::线程(不是QThread)
- Run an
init
function in that thread. Let it instantiate yourQApplication
/QGuiApplication
and start the event loop - 在该线程中运行一个init函数。让它实例化QApplication/QGuiApplication并启动事件循环。
- Ensure that all your GUI objects are accessed from that thread only.
- 确保仅从该线程访问所有GUI对象。
Voila, you now have a GUI thread that is not your main thread.
现在,您有了一个不是主线程的GUI线程。
^Note: It is a different story on Mac OS X. Due to restrictions in the Cocoa framework, the main thread MUST be the GUI thread. The steps I outlined above will work on Windows/Linux but not on Mac. For Mac, you need to inject your code into the main thread -- see Kuba Ober's comments below.
^注意:这是一个不同的故事在Mac OS x上由于Cocoa框架的限制,主要的线程必须GUI线程。我在上面概述的步骤将在Windows/Linux上运行,而不是在Mac上。对于Mac来说,你需要将你的代码注入主线程中——请参见Kuba Ober的评论。
#1
20
Most of the time, "main thread" == "GUI thread", so people use those terms interchangeably -- even the official documentation does that. I agree that it's confusing though, because they don't have to be the same.^ The actual rule is this:
大多数时候,“主线程”=“GUI线程”,所以人们可以互换使用这些术语——甚至官方文档也会这样做。我同意这是令人困惑的,因为它们不一定是相同的。^实际的规则是这样的:
GUI classes must only be accessed from the thread which instantiates
QApplication
/QGuiApplication
只能从实例化QApplication/QGuiApplication的线程访问GUI类。
With a plugin like yours, here is what you need to do:
有了像你这样的插件,以下是你需要做的:
- Create a new
std::thread
(NOT aQThread
) - 创建一个新的std::线程(不是QThread)
- Run an
init
function in that thread. Let it instantiate yourQApplication
/QGuiApplication
and start the event loop - 在该线程中运行一个init函数。让它实例化QApplication/QGuiApplication并启动事件循环。
- Ensure that all your GUI objects are accessed from that thread only.
- 确保仅从该线程访问所有GUI对象。
Voila, you now have a GUI thread that is not your main thread.
现在,您有了一个不是主线程的GUI线程。
^Note: It is a different story on Mac OS X. Due to restrictions in the Cocoa framework, the main thread MUST be the GUI thread. The steps I outlined above will work on Windows/Linux but not on Mac. For Mac, you need to inject your code into the main thread -- see Kuba Ober's comments below.
^注意:这是一个不同的故事在Mac OS x上由于Cocoa框架的限制,主要的线程必须GUI线程。我在上面概述的步骤将在Windows/Linux上运行,而不是在Mac上。对于Mac来说,你需要将你的代码注入主线程中——请参见Kuba Ober的评论。