2017-10-11 4 views
0

Je suis à la retraite et apprends à écrire du code. Je travaille sur un programme qui nécessite un thread pour fonctionner en arrière-plan (interface graphique développée avec PYQT5) afin que je puisse toujours utiliser les boutons de l'interface graphique (pour mettre en pause, reprendre, arrêter, etc.). J'ai le thread comptant jusqu'à 10, et je veux que les étapes soient renvoyées à setValue de la barre de progression. Cela ne fonctionne pas. Je peux voir le fil comptant jusqu'à 10 et je peux voir les données qui reviennent du fil. Juste ne peut pas obtenir la barre de progression pour se déplacer. J'ai passé les deux derniers jours à chercher sur Internet et j'ai passé en revue et essayé de suivre de nombreux exemples. Pour être honnête, je ne suis pas sûr de comprendre les réponses.
J'ai créé un exemple de ce que je vois dans mon programme. Dans cet exemple, j'ai une barre de progression dans une interface graphique avec deux boutons. Démarrer démarre le thread et le test imprime simplement les instructions de test pendant que le thread s'exécute. J'utilise Designer, donc l'interface graphique est dans un fichier séparé.
Je ne sais même pas si je pose correctement les questions dans mes recherches. J'ai décidé de poster dans l'erreur que je vois beaucoup, mais j'espère que vous pouvez voir ce qui se passe lorsque vous exécutez le code.PyQt5 ne peut pas mettre à jour la barre de progression du thread et a reçu l'erreur "Impossible de créer des enfants pour un parent qui se trouve dans un thread différent"

Programme principal

#!/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() 

Voici le code 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")) 

C'est l'erreur que je reçois:

(python3: 11942): AVERTISSEMENT: récupération d'erreur adresse de bus d'accessibilité: org.freedesktop.DBus.Error.ServiceUnknown: Le nom org.a11y.Bus n'a été fourni par aucun fichier .service QO bject: impossible de créer des enfants pour un parent appartenant à un thread différent. (Parent est QApplication (0x26a1a58), le fil de parent est QThread (0x26a6218), thread courant est ExecuteSession (0x28f4048)

Je ne suis pas un développeur de logiciels, tant de ceci est nouveau pour moi. Je vous remercie de toute aide Je peux recevoir, et s'il vous plaît ... ne présumez pas que je sais rien S'il vous plaît être descriptif Merci

+0

S'il vous plaît tester ma réponse et si cela fonctionne n'oubliez pas de marquer ma réponse comme correcte.: P – eyllanesc

Répondre

0

Votre code a plusieurs erreurs depuis PyQt a certaines règles minimales:..!

  • Le fil où l'application GUI est créé est appelé thread graphique parce qu'il doit y avoir créer et vivre n'importe quel composant graphique, mais vous créez RPTApp inutile dans le QThread, je dis inutile puisque le thread est créé dans RPTApp il n'est donc pas nécessaire d'en créer un autre. Une autre erreur est dans l'émission du signal dans le fil, vous ne devez pas appeler la fonction qui utilise les données qui émettent le signal, mais vous devez le connecter à l'emplacement. L'application sera chargée de transporter les données et d'invoquer l'emplacement.

Tous les ci-dessus est corrigée dans la section suivante:

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) 

Note: Il est recommandé de ne pas utiliser int comme variable puisqu'elle est le nom d'une fonction pré-chargé, il y a des milliers d'autres noms.

+0

Fonctionne! Merci beaucoup. J'avais la ligne self.PBValueSig.emit (i) dans la classe ExecuteSession, mais aucun signal ne s'affichait pour mettre à jour la barre de progression. De là, j'essayais n'importe quoi. Je vois maintenant mon erreur ne pas créer la connexion. Merci encore! – Mike

+0

Une autre question. Puisque je suis en train d'apprendre à utiliser des threads, y a-t-il des actions de gestion interne que je dois effectuer dans le code une fois le thread terminé? – Mike