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_())
请帮我解决这个问题。
答案 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::processEvents
和QCoreApplication::flush
:
def ts(self):
glabel.setText(u"Waiting...")
QtCore.QCoreApplication.processEvents()
QtCore.QCoreApplication.flush()
timesleep()