2011-11-04 6 views
5

Esta pregunta parece haber sido formulada muchas veces en muchas formas diferentes, pero no he logrado encontrar una con un -relevante para mi código de solución.Bucle QProgressBar da error >> QObject :: installEventFilter: No se pueden filtrar eventos para objetos en un hilo diferente

Cuando ejecuto el programa que muestra

QObject :: installEventFilter: No se puede filtrar eventos para los objetos en un hilo diferente.

A pesar de esto, el código funciona inicialmente, pero después de un tiempo se bombardea y Python da un error diciendo que dejó de funcionar.

Mi código es el siguiente:

from PyQt4.QtCore import * 
from PyQt4.QtGui import * 
from xml.etree import ElementTree as ET 
import os , time 

class LayoutCreator(QDialog): 
    def __init__(self , parent=None): 
     super(LayoutCreator, self).__init__(parent) 
     self.Cameras_Update() 


    def Cameras_Update(self):            # Get all shots with camera plots and add them to the cameras_tree 
     busyBar = sqrl_QtTools.BusyBar(text = "Gathering Camera Data") # Looping progress bar 
     busyBar.start() 

     # loop through folder structure storing data     

     busyBar.Kill()              # Close looping progress bar  


class BusyBar(QThread):      # Looping progress bar 
    def __init__(self, text = ""): 
     QThread.__init__(self) 
     self.text = text 
     self.stop = False 

    def run(self): 
     self.proBar = QProgressBar() 
     self.proBar.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.SplashScreen) 
     self.proBar.setMinimum(0) 
     self.proBar.setMaximum(100) 
     self.proBar.setTextVisible(True) 
     self.proBar.setFormat(self.text) 
     self.proBar.setValue(0) 
     self.proBar.setFixedSize(500 , 50) 
     self.proBar.setAlignment(Qt.AlignCenter) 
     self.proBar.show() 
     while not self.stop:    # keep looping while self is visible 
      # Loop sending mail 
      for i in range(100): 
       progress = self.proBar.value() 
       progress = progress + 1 
       self.proBar.setValue(progress) 

       time.sleep(0.05) 
      self.proBar.setValue(0) 
     self.proBar.hide() 

    def Kill(self): 
     self.stop = True 

Respuesta

6

No se puede crear o acceder a cualquier QWidget fuera del hilo principal.

Puede utilizar las señales y ranuras para acceder indirectamente a los widgets desde el otro hilo:

from PyQt4.QtCore import * 
from PyQt4.QtGui import * 
import sys, time 

class BusyBar(QThread):      # Looping progress bar 
    # create the signal that the thread will emit 
    changeValue = pyqtSignal(int) 
    def __init__(self, text = ""): 
     QThread.__init__(self) 
     self.text = text 
     self.stop = False 
     self.proBar = QProgressBar() 
     self.proBar.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.SplashScreen) 
     self.proBar.setRange(0, 100) 
     self.proBar.setTextVisible(True) 
     self.proBar.setFormat(self.text) 
     self.proBar.setValue(0) 
     self.proBar.setFixedSize(500 , 50) 
     self.proBar.setAlignment(Qt.AlignCenter) 
     self.proBar.show() 

     self.changeValue.connect(self.proBar.setValue, Qt.QueuedConnection) 
     # Make the Busybar delete itself and the QProgressBar when done   
     self.finished.connect(self.onFinished) 

    def run(self): 
     while not self.stop:    # keep looping while self is visible 
      # Loop sending mail 
      for i in range(100): 
       # emit the signal instead of calling setValue 
       # also we can't read the progress bar value from the thread 
       self.changeValue.emit(i) 
       time.sleep(0.05) 
      self.changeValue.emit(0) 

    def onFinished(self): 
     self.proBar.deleteLater() 
     self.deleteLater() 

    def Kill(self): 
     self.stop = True 

class LayoutCreator(QDialog): 
    def __init__(self , parent=None): 
     super(LayoutCreator, self).__init__(parent) 
     self.Cameras_Update() 

    def Cameras_Update(self):          
     # Looping progress bar 
     self.busyBar = BusyBar(text = "Gathering Camera Data") 
     self.busyBar.start() 

     # loop through folder structure storing data 

     # Simulate async activity that doesn't block the GUI event loop 
     # (if you do everything without giving control back to 
     # the event loop, you have to call QApplication.processEvents() 
     # to allow the GUI to update itself) 
     QTimer.singleShot(10000, self.stopBar) 

    def stopBar(self): 
     self.busyBar.Kill()      # Close looping progress bar  

app = QApplication(sys.argv) 
win = LayoutCreator() 
win.show(); 
sys.exit(app.exec_()) 

O

Si sólo desea un indicador de ocupado, sólo tiene que fijar tanto el mínimo y máximo de QProgressBar a 0, y no necesitará un hilo, como se indica en la documentación.

+0

Gracias pero parece que no puedo hacer que su ejemplo funcione. ¿Podría por favor darme un ejemplo del código que usa para ejecutar esto ya que todavía estoy recibiendo errores? – Jared

+0

@mushu Agregué el resto del código que utilicé. – alexisdm

+0

Impresionante. Funciona como un encanto, gracias – Jared

Cuestiones relacionadas