使用PyQT4时订单执行功能出现问题

时间:2013-02-08 12:06:19

标签: python pyqt4

PyQT4 for Python存在问题。有一个标签,文字和按钮连接到功能。该函数可以先更改标签文本,然后调用其他函数。它有一个问题:函数执行firts,然后更改标签的文本。

代码:

# -*- coding: utf-8 -*-
import time
import sys
from PyQt4 import QtCore, QtGui

def timesleep():
    print("start sleep")
    time.sleep(5)
    print("stop sleep")



class AnyWidget(QtGui.QWidget):
    def __init__(self,*args):

        QtGui.QWidget.__init__(self,*args)
        self.setWindowTitle("PETHARD")
        boxlay = QtGui.QHBoxLayout(self)
        frame = QtGui.QFrame(self) # Фрейм
        frame.setFrameShape(QtGui.QFrame.StyledPanel)
        frame.setFrameShadow(QtGui.QFrame.Raised)

        gridlay = QtGui.QGridLayout(frame) # Менеджер размещения элементов во фрейме
        label = QtGui.QLabel(u"Welcome",frame) # Текстовая метка.
        global glabel
        glabel = label
        gridlay.addWidget(label,0,0)
        button1 = QtGui.QPushButton(u"Load From MC", frame)
        self.connect(button1, QtCore.SIGNAL("clicked()"), self.ts)
        gridlay.addWidget(button1,1,0)
        boxlay.addWidget(frame)

    def ts(self):
        global glabel
        glabel.setText(u"Waiting...")
        timesleep()

if __name__=="__main__":
    app = QtGui.QApplication(sys.argv)
    aw = AnyWidget()
    aw.show()
    sys.exit(app.exec_())

请帮我解决这个问题。

3 个答案:

答案 0 :(得分:2)

它的工作方式就像那样,因为渲染是在应用程序中稍后完成的。因此,glabel.text会立即更改,但您会在ts函数调用后在屏幕上看到更改的文本,因为绘制是在循环结束时完成的。

如果你真的想在新帧中调用你的函数(在渲染新文本之后),那么使用timer:

timer = QtCore.QTimer()
QtCore.QObject.connect(
    timer,
    QtCore.SIGNAL("timeout()"),
    self.ts
)
timer.start(10)

它应该在十几毫秒之后调用你的函数,所以实际上可能在渲染之后。

答案 1 :(得分:1)

您永远不希望将GUI与长时间运行的功能联系起来。标签不更新只是问题的一种表现形式。即使您在调用函数之前更新了标签,它仍然会“冻结”您的GUI - 在长时间运行的函数完成之前,任何小部件都不会响应用户。

如果你必须运行这样一个函数,看看是否有办法将它分解为小部分,每个部分放弃对GUI的控制,或者考虑使用单独的线程来运行该函数:

import time
import sys
from PyQt4 import QtCore, QtGui


class TimeSleep(QtCore.QThread):
    def __init__(self, parent=None):
        QtCore.QThread.__init__(self, parent)
        self.parent = parent

    def run(self):
        print("start sleep")
        time.sleep(5)
        print("stop sleep")
        self.parent.glabel.setText(u"Done")


class AnyWidget(QtGui.QWidget):
    def __init__(self, *args):

        QtGui.QWidget.__init__(self, *args)
        self.setWindowTitle("PETHARD")
        boxlay = QtGui.QHBoxLayout(self)
        frame = QtGui.QFrame(self)  # Фрейм
        frame.setFrameShape(QtGui.QFrame.StyledPanel)
        frame.setFrameShadow(QtGui.QFrame.Raised)

        gridlay = QtGui.QGridLayout(
            frame)  # Менеджер размещения элементов во фрейме
        label = QtGui.QLabel(u"Welcome", frame)  # Текстовая метка.
        self.glabel = label
        gridlay.addWidget(label, 0, 0)
        button1 = QtGui.QPushButton(u"Load From MC", frame)
        self.connect(button1, QtCore.SIGNAL("clicked()"), self.ts)
        gridlay.addWidget(button1, 1, 0)
        boxlay.addWidget(frame)

    def ts(self):
        self.glabel.setText(u"Waiting...")
        self.thread = TimeSleep(parent=self)
        self.thread.start()


if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    aw = AnyWidget()
    aw.show()
    sys.exit(app.exec_())

这是关于如何处理长时间运行的函数的wiki page

答案 2 :(得分:1)

标签的文字正在改变,但是因为你阻止了主线程,所以你没有给Qt画一个机会。

使用QCoreApplication::processEventsQCoreApplication::flush

def ts(self):
    glabel.setText(u"Waiting...")
    QtCore.QCoreApplication.processEvents()
    QtCore.QCoreApplication.flush()
    timesleep()
相关问题