2017-10-11 53 views
0

我已退休並自學編寫代碼。我正在研究需要線程在後臺運行的程序(使用PYQT5開發的GUI),所以我仍然可以使用GUI按鈕(暫停,恢復,停止等)。我有線程數到10,並且我想要將這些步驟發送回進度條的setValue。這不起作用。我可以看到線程數爲10,我可以看到線程返回的數據。只是無法讓進度條移動。 我花了最近兩天搜索互聯網,並審查並試圖遵循很多例子。說實話,我不知道我明白答案。
我列舉了我在程序中看到的一個例子。在這個例子中,我有一個帶有兩個按鈕的GUI的進度條。開始將啓動線程,測試將在線程運行時打印出測試語句。我正在使用Designer,所以GUI在單獨的文件中。
我甚至不確定我是否在我的搜索中正確提問。我決定發佈錯誤,我看到很多,但希望你能看到當你運行代碼時發生了什麼。PyQt5無法從線程更新進度欄,並收到錯誤「無法爲處於不同線程中的父項創建子項」

主程序

#!/usr/bin/env python3 

import sys, sqlite3, os.path, string, time 
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, 
QProgressBar 
from PyQt5.QtCore import pyqtSlot, QObject, QThread, pyqtSignal 
from Thread_Test import Ui_MainWindow 

class ExecuteSession(QThread): 

    PBValueSig = pyqtSignal(int) 

    def __init__(self, dur=0): 
     QThread.__init__(self) 
     self.dur = dur 

    def __del__(self): 
     self.wait() 

    def run(self): 
     i = 0 
     while i <= self.dur: 
      self.RPTApp = RPTApp() 
      print(i) 
      i = i + 1 
      self.PBValueSig.emit(self.RPTApp.updateProgressBar(i))  
      time.sleep(1) 



class RPTApp(QMainWindow, Ui_MainWindow): 


    def __init__(self, parent=None): 
     super(RPTApp, self).__init__(parent) 
     self.setupUi(self) 

     self.pushButton.clicked.connect(self.PB) 
     self.pushButton_2.clicked.connect(self.PB2) 

    def PB2(self): 
     print("TEST") 


    def PB(self): 
     dur = 10 
     self.progressBar.setMinimum(0) 
     self.progressBar.setMaximum(dur) 
     self.progressBar.setValue(0) 
     #thread 
     self.exeThread = ExecuteSession(dur) 
     self.exeThread.start()   


    @pyqtSlot(int) 
    def updateProgressBar(self, int): 
     print("INT + " +str(int)) 
     #self.classES.PBValueSig.connect(self.progressBar.setValue) 
     self.progressBar.setValue(int) 

def main(): 

    app = QApplication(sys.argv) 
    window = RPTApp() 
    window.show() 
    app.exec_()  


if __name__ == '__main__': 
    main() 

這是GUI代碼:

# -*- coding: utf-8 -*- 

# Form implementation generated from reading ui file 'Thread_Test.ui' 
# 
# Created by: PyQt5 UI code generator 5.7 
# 
# WARNING! All changes made in this file will be lost! 

from PyQt5 import QtCore, QtGui, QtWidgets 

class Ui_MainWindow(object): 
    def setupUi(self, MainWindow): 
     MainWindow.setObjectName("MainWindow") 
     MainWindow.resize(640, 480) 
     self.centralwidget = QtWidgets.QWidget(MainWindow) 
     self.centralwidget.setObjectName("centralwidget") 
     self.progressBar = QtWidgets.QProgressBar(self.centralwidget) 
     self.progressBar.setGeometry(QtCore.QRect(90, 320, 471, 23)) 
     self.progressBar.setProperty("value", 24) 
     self.progressBar.setObjectName("progressBar") 
     self.pushButton = QtWidgets.QPushButton(self.centralwidget) 
     self.pushButton.setGeometry(QtCore.QRect(270, 140, 91, 29)) 
     self.pushButton.setObjectName("pushButton") 
     self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget) 
     self.pushButton_2.setGeometry(QtCore.QRect(270, 200, 91, 29)) 
     self.pushButton_2.setObjectName("pushButton_2") 
     MainWindow.setCentralWidget(self.centralwidget) 

     self.retranslateUi(MainWindow) 
     QtCore.QMetaObject.connectSlotsByName(MainWindow) 

    def retranslateUi(self, MainWindow): 
     _translate = QtCore.QCoreApplication.translate 
     MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) 
     self.pushButton.setText(_translate("MainWindow", "START")) 
     self.pushButton_2.setText(_translate("MainWindow", "TEST")) 

這是我收到錯誤:

(python3:11942):警告:錯誤檢索無障礙總線地址:org.freedesktop.DBus.Error.ServiceUnknown:名稱org.a11y.Bus未被任何服務文件提供 QO bject:無法爲處於不同線程中的父項創建子項。 (Parent是QApplication的(0x26a1a58),父母的線程的QThread(0x26a6218),當前線程是ExecuteSession(0x28f4048)

我不是一個軟件開發人員,這麼多的,這是新的我。我感謝所有幫助我可以接受,並請......不要以爲我一無所知請描述謝謝

+0

請測試我的答案,如果它的工作不要忘記標記我的答案是正確的。:P – eyllanesc

回答

0

你的代碼中有幾個錯誤,因爲PyQt的有一定的最低限度規則:!

  • 線程哪裏GUI應用程序被創建稱爲GUI線程,因爲必須有創建並生活任何圖形組件,但是您在QThread中創建不必要的RPTApp,因爲該線程是在RPTApp內部創建的,所以不需要創建另一個。

  • 另一個錯誤是導線中信號的發射,您不必調用使用發射信號的數據的功能,但必須將其連接到插槽。應用程序將負責傳輸數據和調用插槽。

上述所有在下面的部分進行修正:

class ExecuteSession(QThread): 
    PBValueSig = pyqtSignal(int) 
    [...] 
    def run(self): 
     i = 0 
     while i <= self.dur: 
      print(i) 
      i = i + 1 
      self.PBValueSig.emit(i) 
      time.sleep(1) 


class RPTApp(QMainWindow, Ui_MainWindow): 
    [..] 
    def PB(self): 
     dur = 10 
     self.progressBar.setMinimum(0) 
     self.progressBar.setMaximum(dur) 
     self.progressBar.setValue(0) 
     # thread 
     self.exeThread = ExecuteSession(dur) 
     self.exeThread.PBValueSig.connect(self.updateProgressBar) 
     self.exeThread.start() 

    @pyqtSlot(int) 
    def updateProgressBar(self, value): 
     print("INT + " + str(value)) 
     self.progressBar.setValue(value) 

注:不建議INT使用的變量,因爲它是一個預加載函數的名字,也有成千上萬的其他名字。

+0

作品!非常感謝你。我在ExecuteSession類中有self.PBValueSig.emit(i),但沒有信號顯示出來更新進度條。從那裏我正在嘗試任何東西。我現在看到我的錯誤沒有創建連接。再次感謝! – Mike

+0

另一個問題。由於我正在學習使用線程,當線程完成時,我需要在代碼中執行哪些管家操作? – Mike

相關問題