5

这个问题似乎已经以许多不同的形式被问过很多次,但我还没有找到一个与我的代码解决方案相关的问题。

当我运行程序时它显示

QObject::installEventFilter:无法过滤不同线程中对象的事件。

尽管如此,代码最初可以工作,但一段时间后它会爆炸,python 会给出一个错误,说它停止工作。

我的代码如下:

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
4

1 回答 1

7

您不能QWidget在主线程之外创建或访问任何内容。

您可以使用信号和插槽从其他线程间接访问小部件:

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_())

或者

如果您只想要一个繁忙的指示器,您可以简单地将 的最小值和最大值都设置QProgressBar为 0,并且您不需要线程,如文档中所述。

于 2011-11-05T03:17:57.633 回答