2016-10-24 19 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が動作する方法です.GUIは、多くの人が何らかの順序で考えているループ(mainloopまたはevent loop)を実行します。マウス/キーボードイベントを取得し、ウィジェットに送信し、機能を実行し、最後にウィジェットを更新/再描画します。したがって、関数内のテキストを変更すると、画面上で即座に更新/再描画されません。それはあなたの機能を終了した後に後で行います。だから、長時間実行している機能を実行すると、変更されたテキストは表示されません。また、マウスとキーボードでウィンドウが反応しません。

あなたは更新を強制的に

app.processEvents() 

を使用することができますが、まだあなたは、マウスやキーボードのイベントに応答して、問題を持っています。 2番目のスレッドで計算を実行する必要があります。

このコードは私には役立ちますが、理想的ではありません。

(2番目のスレッドが直接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') 
関連する問題