QApplication在带有pyQt4的第二个进程的非主线程中:此代码合法,如果不合法,为什么起作用?

问题描述 投票:-1回答:1

我和我的合作者已经在python 2.7和pyQt4中编程了一个集成开发环境(IDE),该集成环境已经运行了十多年了。现在,我必须将其移植到pyqt5上,然后遇到一些问题。这篇文章与我的第一个问题有关。在声明为重复副本之前,请认真阅读底部的问题。这是因为我不理解相关帖子中我在这里提出其他确切问题的答案。

我的IDE的体系结构如下:

  • 主IDE应用程序是在第一个进程中运行的QApplication(例如P1)
  • 第二个过程(例如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),并且一切正常。

现在我的问题是:

  1. 上面的代码是否违反了任何Qt4规则,因为它在非主线程中启动了QApplication?

  2. QT4文档的哪个页面告诉我们禁止像我们一样进行处理?

  3. 进程的主线程的定义是什么?运行process.run()函数的线程?

  4. 什么是Qt主线程?按照定义,它是进程的主线程,还是可以是另一个线程?

  5. 我们为什么不出现错误“主线程中未创建QApplication”?

  6. Qt4如何识别事件循环是否正在进程的主线程中运行?

python multithreading pyqt4 python-multiprocessing qapplication
1个回答
0
投票

可以找到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上。

如果有任何错误,请更正此答案。

© www.soinside.com 2019 - 2024. All rights reserved.