如何显示 PySide/PyQt UI 并自动运行其中一种方法?

Posted

技术标签:

【中文标题】如何显示 PySide/PyQt UI 并自动运行其中一种方法?【英文标题】:How to show PySide/PyQt UI and auto-run one of its methods? 【发布时间】:2014-10-03 15:01:41 【问题描述】:

我希望打开一个 PySide/PyQt 窗口并自动开始执行一个方法,该方法将在执行时在 UI 中显示一个进度。

使用下面的代码,直到过程完成后才会显示 ui,因此您看不到进度。如何在流程完成之前更改代码以查看进度?

from PySide import QtGui
import time

class MyApp(QtGui.QMainWindow)
    def __init__(self, parent=None):
        super(MyApp, self).__init__(parent)

        # Setup
        self.centralWidget = QtGui.QWidget(self)
        self.setCentralWidget(self.centralWidget)
        self.setup_UI()

        # Execute process!
        self.process()

    def setup_UI(self):
        ''' Attach widgets to window '''
        self.mainLayout=QtGui.QVBoxLayout(self.centralWidget)
        self.list_widget = QtGui.QListWidget()
        self.progress_bar = QtGui.QProgressBar()
        self.mainLayout.addWidget(self.list_widget)
        self.mainLayout.addWidget(self.progress_bar)

    def process(self):
        ''' Manipulate the ui '''
        self.progress_bar.setMaximum(0)
        self.progress_bar.setMaximum(10)

        for x in range(0, 10):
            time.sleep(1)
            self.list_widget.addItem('Item ' + str(x))
            self.progress_bar.setValue(x)



my_app = MyApp()
my_app.show()

【问题讨论】:

【参考方案1】:

您通过调用time.sleep 阻塞qt 主线程的主要问题。要解决此问题,您有两种选择。其中之一是using threading。另一种选择是将您的代码更改为异步,如下所示:

from PySide import QtGui, QtCore
import time
import sys

class MyApp(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MyApp, self).__init__(parent)

        # Setup
        self.centralWidget = QtGui.QWidget(self)
        self.setCentralWidget(self.centralWidget)
        self.setup_UI()

        # Execute process!
        self.set_process()
        self.timer = QtCore.QTimer()
        self.i = 0
        self.timer.timeout.connect(self.update)
        self.timer.start(1000)

    def setup_UI(self):
        ''' Attach widgets to window '''
        self.mainLayout=QtGui.QVBoxLayout(self.centralWidget)
        self.list_widget = QtGui.QListWidget()
        self.progress_bar = QtGui.QProgressBar()
        self.mainLayout.addWidget(self.list_widget)
        self.mainLayout.addWidget(self.progress_bar)

    def set_process(self):
        ''' Manipulate the ui '''
        self.progress_bar.setMaximum(0)
        self.progress_bar.setMaximum(10)

    def update(self):
        if self.i > 9:
            self.timer.stop()

        self.list_widget.addItem('Item ' + str(self.i))
        self.progress_bar.setValue(self.i)
        self.i += 1


def main():
    app = QtGui.QApplication(sys.argv)
    my_win = MyApp()
    my_win.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

此示例使用Qtimer 对象延迟更新进度条。

【讨论】:

【参考方案2】:

通过使用single-shot timer 开始处理,然后在循环中调用processEvents 来更新GUI,可以很容易地使示例工作:

    # Execute process!
    QtCore.QTimer.singleShot(100, self.process)

    ...

    for x in range(0, 10):
        time.sleep(1)
        ...
        QtGui.qApp.processEvents(QtCore.QEventLoop.AllEvents, 50)

但是,不能保证这种方法适用于更现实的示例。您最终可能需要使用线程或多处理 - 这完全取决于您要执行的特定类型的处理。

【讨论】:

以上是关于如何显示 PySide/PyQt UI 并自动运行其中一种方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PySide/PyQt 中设置“只读复选框”

Python: PySide(PyQt)QMessageBox按钮显示中文

如何创建一个新的窗口按钮 PySide/PyQt?

PySide/pyQt 在 QTableView 中显示数据

访问 QMainWindow 类变量 - Pyside/PyQt

在 QTextBrowser 中突出显示文本时发送 PySide/PyQt 信号