2016-10-24 74 views
0

我使用pyqt構建了一個小gui,您可以從QComboBox中選擇一個Key,然後使用Value進行數學計算,通常需要3秒,結果是一個短的字符串。我正在更新文本框中gui中計算的短字符串。這是我的代碼(我刪除了數學運算的代碼,因爲它是不相關的),它是工作迄今:試圖在計算時更新pyqt中的文本框

import sys 
from PyQt4.QtCore import * 
from PyQt4.QtGui import * 
import os 
dict1 = {"Key":Value, "Key2":Value2, "Key3":Value3} # Value are int's 

class combodemo(QWidget): 
    def __init__(self, parent = None): 
    super(combodemo, self).__init__(parent) 

    layout = QHBoxLayout() 
    self.cb = QComboBox() 
    self.cb.addItems([key for key in sorted(dict1.keys())]) 
    self.cb.currentIndexChanged.connect(self.selectionchange) 

    layout.addWidget(self.cb) 
    self.setLayout(layout) 
    self.cb.textbox = QLineEdit(self) 
    self.cb.textbox.move(100, 200) 
    self.cb.textbox.resize(150,50) 
    self.cb.textbox.setAlignment(Qt.AlignCenter) 
    self.cb.textbox.setText("Initial Text") 

    def selectionchange(self): 
    #self.cb.textbox.setText("Calculating...") # THIS IS NOT WORKING 
    self.cb.currentIndexChanged.connect(self.selectionchange) 
    # MATH CALCULATION CODE GOES HERE[...] 
    self.cb.textbox.setText("RESULT OF MATH CALCULATION") 

def main(): 
    app = QApplication(sys.argv) 
    ex = combodemo() 
    ex.show() 
    sys.exit(app.exec_()) 

if __name__ == '__main__': 
    main() 

眼下程序Key選擇後凍結3秒(因爲數學計算我的我在做)。由於我的數學計算需要3秒鐘,所以一旦選擇QComboBox的Key,我想將文本框更新爲"Calculating..."。所以,當我的數學計算執行時,我希望文本框顯示"Calculating..."。計算完成後,應該簡單地重寫文本框並顯示數學結果。

在上面的代碼中,我試圖在函數def selectionchange(self)的開頭(它未被註釋)實現它。但它沒有效果。我該如何做這項工作?

回答

0

這是如何大多數圖形用戶界面的工作原理:GUI運行循環(稱爲mainloopevent loop),其中做了很多認爲以某種順序:它得到的鼠標/鍵盤事件,並將其發送到窗口小部件,運行你的職責,做其他的東西,在最後更新/重繪小部件。所以當你改變你的函數中的文本時,它不會立即更新/重繪它在屏幕上。它在結束你的功能後再做。所以如果你運行長時間運行的函數,那麼你不會立即看到改變的文本(並且窗口不響應鼠標和鍵盤)。

您可以使用

app.processEvents() 

強制更新,但你仍然有問題,對鼠標和鍵盤事件的響應。你必須在第二個線程中運行計算。

此代碼適用於我,但並不理想。

(第二線程不應該直接改變GUI - 它應該發送消息/信號,第一個線程因此,有更好的解決辦法:Simplest way for PyQT Threading

from PyQt4.QtCore import * 
from PyQt4.QtGui import * 
import os,sys 

import time # to simulate long-running function 
import threading 

dict1 = {"Key":100, "Key2":200, "Key3":300} # Value are int's 

class ComboDemo(QWidget): 

    def __init__(self, parent = None): 
    super(ComboDemo, self).__init__(parent) 

    layout = QHBoxLayout() 
    self.cb = QComboBox() 
    self.cb.addItems([key for key in sorted(dict1.keys())]) 
    self.cb.currentIndexChanged.connect(self.selectionchange) 

    layout.addWidget(self.cb) 
    self.setLayout(layout) 
    self.cb.textbox = QLineEdit(self) 
    self.cb.textbox.move(100, 200) 
    self.cb.textbox.resize(150,50) 
    self.cb.textbox.setAlignment(Qt.AlignCenter) 
    self.cb.textbox.setText("Initial Text") 

    def selectionchange(self): 
    self.cb.textbox.setText("Calculating...") 

    # get value from dict using selected key 
    value = dict1[str(self.cb.currentText())] 

    # run thread - args has to be tuple 
    t = threading.Thread(target=self.calculation, args=(value,)) 
    t.start() 

    def calculation(self, arg): 
    # MATH CALCULATION CODE GOES HERE[...] 
    time.sleep(3) # to simulate long-running function 
    self.cb.textbox.setText("RESULT: " + str(arg)) 


def main(): 

    app = QApplication(sys.argv) 
    ex = ComboDemo() 
    ex.show() 
    sys.exit(app.exec_()) 

if __name__ == '__main__': 
    main() 
0

你可能在你一個進度條,以向用戶示出計算正在進行中。下面是一個例子(整個代碼是http://zetcode.com/gui/pyqt4/widgets/

def initUI(self):  

    self.pbar = QtGui.QProgressBar(self) 
    self.pbar.setGeometry(30, 40, 200, 25) 

    self.btn = QtGui.QPushButton('Start', self) 
    self.btn.move(40, 80) 
    self.btn.clicked.connect(self.doAction) 

    self.timer = QtCore.QBasicTimer() 
    self.step = 0 


def timerEvent(self, e): 

    if self.step >= 100: 

     self.timer.stop() 
     self.btn.setText('Finished') 
     return 

    self.step = self.step + 1 
    self.pbar.setValue(self.step) 

def doAction(self): 

    if self.timer.isActive(): 
     self.timer.stop() 
     self.btn.setText('Calculating ...') 

    else: 
     self.timer.start(100, self) 
     self.btn.setText('Stop')