簡體   English   中英

QApplication 在 pyQt4 的第二個進程的非主線程中:這段代碼是否合法,如果不合法,為什么它有效?

[英]QApplication in a non-main thread of second process with pyQt4: is this code legal, and if not, why does it work?

我和我的合作者用 python 2.7 和 pyQt4 編寫了一個集成開發環境 (IDE),它已經完美運行了十多年。 我現在必須將它移植到 pyqt5,但我遇到了幾個問題。 這篇文章與我的第一個問題有關。 在將其聲明為重復之前,請仔細閱讀底部的問題。 這是因為我不明白我在這里問其他精確問題的相關帖子中的答案。

我的 IDE 的架構如下:

  • 主要的 IDE 應用程序是在第一個進程中運行的 QApplication(比如 P1)
  • 第二個進程(比如 P2)由 P1 創建。 P2 的主線程運行無限循環,等待來自 P1 的代碼片段(通過隊列)在 P2 的不同非主線程中執行。

  • 雖然大部分要運行的代碼段是非 gui 的,但 P2 的一個(並且只有一個)非主線程是一個 Qt 線程,運行一個可以運行 Qt 代碼段的 QApplication。

  • 這個 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 的任何線程中運行 execinGUI(f) 時,QApplication 是在一個新的其他非主線程中創建的,或者如果它已經存在則被檢索(像這樣只有一個進程 P2 中的 QThread),一切正常。

現在我的問題是:

  1. 上面的代碼是否違反了任何 Qt4 規則,因為它在非主線程中啟動了 QApplication?

  2. QT4文檔的哪一頁告訴我們禁止像我們所做的那樣處理?

  3. 進程主線程的定義是什么? 運行 process.run() 函數的線程?

  4. 什么是 Qt 主線程? 根據定義,它是進程的主線程還是可以是另一個線程?

  5. 為什么我們沒有錯誤“QApplication 未在主線程中創建”?

  6. Qt4 如何識別事件循環是否在進程的主線程中運行?

對這些問題的答案的很多元素在這里問,可以發現(同時看到答案和評論,從JKSH特別是)。

總而言之,“主線程”的含義對於 Qt 和系統而言可能不同,具體取決於平台。 在 linux 和 windows 上,Qt 的主線程只是第一個與 Qt 相關的線程(小心所有其他線程中的導入)。 它不是運行 process.run() 的線程。 在 OS X 中,情況有所不同,Qt 和進程的“主線程”是相同的。 在這方面,這些文件似乎被專家認為是不准確的......

因此,對這篇文章的確切問題的初步答案是:

1) 上面的代碼是否違反了任何 Qt4 規則,因為它在非主線程中啟動了 QApplication?

=> 沒有

2)QT4文檔的哪一頁告訴我們禁止像我們所做的那樣處理?

=> 無,因為“主線程”從未在 pyQt4 文檔中正確定義

3)進程主線程的定義是什么? 運行 process.run() 函數的線程?

=> 是的

4)什么是Qt主線程? 根據定義,它是進程的主線程還是可以是另一個線程?

=> 它是引用第一個 Qt 對象的線程(注意進程主線程中的導入)。 它不是進程的主線程。 它們可以不同。

5)為什么我們沒有錯誤“QApplication was not created in the main thread”?

=> 因為它是在Qt所謂的“主線程”中創建的,雖然它與進程所謂的“主線程”不同。

6) Qt4 如何識別事件循環是否在進程的主線程中運行?

=> 它根本不在 Windows 和 linux 上。

如果此答案包含任何錯誤,請更正此答案。

Qt 文檔中沒有明確定義主線程的概念。 實際上,進程的主線程(執行 Process.run 函數的進程)可以不同於主 Qt 線程(像 QApplication 一樣實例化第一個 Qt 對象的線程),盡管兩個“主”線程通常是相同的.

有效代碼結構示例:

下面的函數將在進程'非主線程'thread-1'中運行,它將立即成為Qt的主線程。

def startThread1():      
    app = QApplication(sys.argv)
    app.exec_()  # enter event loop

下面的代碼在進程的主線程中運行,不要與進程的主 Qt 和獨特的 GUI 線程混淆。

thread1 = Thread(target=self.startThread1)
thread1.start()
input('I am busy until you press enter')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM