我和我的合作者已经在python 2.7和pyQt4中编程了一个集成开发环境(IDE),该集成环境已经运行了十多年了。现在,我必须将其移植到pyqt5上,然后遇到一些问题。这篇文章与我的第一个问题有关。在声明为重复副本之前,请认真阅读底部的问题。这是因为我不理解相关帖子中我在这里提出其他确切问题的答案。
我的IDE的体系结构如下:
第二个过程(例如P2)由P1创建。 P2的主线程运行一个无限循环,等待P1中的代码段(通过队列)在P2的不同非主线程中执行。
尽管大多数要运行的代码段都是非gui的,但P2的非主线程中的一个(只有一个)是运行QApplication的Qt线程,该QApplication可以运行Qt的代码段。
此QApplication(例如app)具有一个以app.exec_()开始的常规事件循环,但也可以接收带有gui函数的信号以作为相应插槽的参数运行。
这里是用于此目的的代码,效果很好。 (不幸的是,我无法在此处粘贴合理大小的独立代码,但足以理解并回答问题)
"""
This model helps to execute GUI code in a QT thread.
"""
import time, sys
from threading import Thread
from PyQt4.QtCore import *
from PyQt4.QtGui import *
#from pyview.identifyThreads import identify
signalConnected = False
def _runGuiCodeSignal(f):
f()
def execInGui(f):
_ensureGuiThreadIsRunning()
global app
if app == None:
raise Exception("Invalid application handle!")
app.emit(SIGNAL("runGuiCode(PyQt_PyObject)"), f)
def _createApplication():
#from pyview.identifyThreads import identify
global app
global signalConnected
global _runGuiCodeSignal
app = QApplication(sys.argv) #
app.setQuitOnLastWindowClosed(False) #
app.connect(app, SIGNAL("runGuiCode(PyQt_PyObject)"), _runGuiCodeSignal, Qt.QueuedConnection | Qt.UniqueConnection)
signalConnected = True
if app.thread() != QThread.currentThread():
raise Exception("Cannot start QT application from side thread! You will have to restart your process...")
#identify(message='in createApplication just before app.exec')
app.exec_()
def _ensureGuiThreadIsRunning():
#from pyview.identifyThreads import identify
global app
global signalConnected
global _runGuiCodeSignal
app = QApplication.instance()
if app == None:
thread = Thread(target=_createApplication)
#identify('in _ensureGuiThreadIsRunning')
print "Creating new Qt application in thread ", thread
thread.daemon = True
thread.start()
while thread.is_alive() and (app == None or app.startingUp()):
time.sleep(0.01)
else:
if not signalConnected:
print app.connect(app, SIGNAL("runGuiCode(PyQt_PyObject)"), _runGuiCodeSignal,
Qt.QueuedConnection | Qt.UniqueConnection)
signalConnected = True
[当定义一个函数f来创建带有各种小部件的QWindow并在P2的ANY线程中运行execinGUI(f)时,将在另一个新的非主线程中创建QApplication,或者如果它已经存在则进行检索(如进程P2中只有一个QThread),并且一切正常。
现在我的问题是:
上面的代码是否违反了任何Qt4规则,因为它在非主线程中启动了QApplication?
QT4文档的哪个页面告诉我们禁止像我们一样进行处理?
进程的主线程的定义是什么?运行process.run()函数的线程?
什么是Qt主线程?按照定义,它是进程的主线程,还是可以是另一个线程?
我们为什么不出现错误“主线程中未创建QApplication”?
Qt4如何识别事件循环是否正在进程的主线程中运行?
可以找到there此处提出的问题的答案的许多要素(请参见答案和评论,特别是来自JKSH的评论)。
总而言之,对于Qt和系统,“主线程”的含义可能有所不同,具体取决于平台。在Linux和Windows上,Qt的主线程只是与Qt有关的第一个线程(请注意所有其他线程的导入)。不是运行process.run()的线程。在OS X中,情况有所不同,并且Qt和进程的“主线程”相同。在这方面,专家们似乎认为该文件是不准确的...
因此,对本文的确切问题的初步答案是:
1)上面的代码是否因为在非主线程中启动QApplication而违反了任何Qt4规则?
=>否
2)QT4文档的哪一页告诉我们禁止像我们一样进行处理?
=>无,因为在pyQt4文档中从未正确定义“主线程”]
3)进程的主线程的定义是什么?运行process.run()函数的线程?
=>是
4)什么是Qt主线程?按照定义,它是进程的主线程,还是其他线程?
=>这是引用第一个Qt对象的线程(请注意进程主线程中的导入)。它不是进程的主线程。它们可以不同。
5)为什么我们没有错误“未在主线程中创建QApplication”?
=>因为它是在Qt所谓的“主线程”中创建的,尽管它与进程所说的“主线程”不同。
6)Qt4如何识别事件的循环是否正在进程的主线程中运行?
=>它根本不在Windows和Linux上。
如果有任何错误,请更正此答案。