2013-02-08 76 views
0

我的PyQT4 for Python有問題。有一個文本和按鈕連接到功能的標籤。該功能可以先改變標籤的文字,然後再調用其他功能。它有一個問題:函數執行firts,然後更改標籤的文本。使用PyQT4時的訂單執行功能的問題

代碼:

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

請幫我解決這個問題。

回答

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

它的工作就是這樣,因爲渲染稍後在app中完成。因此,您的glabel.text會立即更改,但您會在調用ts函數後在屏幕上看到更改後的文本,因爲繪製是在循環結束時完成的。

如果你真的想調用新的幀(渲染新文本後價格)的函數,然後使用定時器:

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

它也許應該在渲染之後再打你的函數10 milisecond,所以實際上。

1

標籤的文本正在改變,但是因爲你阻止了主線程,所以你不會給Qt一個繪製它的機會。

使用QCoreApplication::processEventsQCoreApplication::flush

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