1

私はしばらくこれに苦労してきました。私がやりたいことを説明しようと思います。多分皆さんが私を助けてくれます。

それで、ステータスラベルが付いたGUIと、次のような2つのループがあるとしましょう:

for _a in range(3000):
     self.changeLabel('_a= '+ str(_a))

for _b in range(5000):
     self.changeLabel('_b=' + str(_b))

def changeLabel(self,_text):
     self.ui.STATUS.setText(_text)   <---ui is a GUI where label is placed. 
     APP.processEvents()               

STARTが押された(完了した)後にラベル(STATUS)を結果で更新し、STOPボタンが押されているときにループをキャンセルしたい。

スレッド、QEventloop、またはその他の方法 (存在する場合) を使用してこれを達成する方法。私は PyQT の初心者なので、誰かが何か考えを持っている場合は共有してください。

ありがとう。

4

3 に答える 3

2

これを実現する最も簡単な方法は、ジェネレーターと「アイドルタイマー」を使用することです。

アイデアは、yieldキーワードを使用してループをジェネレーターに変換し、を使用して外部から各反復をトリガーできるようにすることですnext()。次に、Qtの低レベルタイマー(、、、startTimer()およびkillTimer()timerEvent()を使用して、間隔がゼロのタイマーを作成します。これは、処理するイベントがなくなるたびに呼び出され、次のループ反復を実行します。これにより、ループ中にGUIイベントに反応する機会が与えられます。たとえば、停止ボタンclicked()信号を処理することができます。

class MyWidget(QWidget):  # Or whatever kind of widget you are creating

    def __init__(self, parent, **kwargs):
        super(MyWidget, self).__init__(parent, **kwargs)
        # ... Create your widgets, connect signals and slots, etc.
        self._generator = None
        self._timerId = None

    def loopGenerator(self):
        # Put the code of your loop here
        for a in range(3000):
            self.ui.STATUS.setText("a=" + a)
            # No processEvents() needed, just "pause" the loop using yield
            yield

    def start(self):  # Connect to Start-button clicked()
        self.stop()  # Stop any existing timer
        self._generator = self.loopGenerator()  # Start the loop
        self._timerId = self.startTimer(0)   # This is the idle timer

    def stop(self):  # Connect to Stop-button clicked()
        if self._timerId is not None:
            self.killTimer(self._timerId)
        self._generator = None
        self._timerId = None

    def timerEvent(self, event):
        # This is called every time the GUI is idle.
        if self._generator is None:
            return
        try:
            next(self._generator)  # Run the next iteration
        except StopIteration:
            self.stop()  # Iteration has finshed, kill the timer
于 2011-08-29T06:33:58.600 に答える
2

フェルディナンドの答えは、 processEvents() を使用して独自のイベントループを作成することを回避するという点で優れています。ただし、もっと簡単な解決策があると思います。停止ボタンが押されたときにフラグを設定し、フラグが設定されている場合はループを終了しないのはなぜですか? 何かのようなもの:

def stopClicked(self):
    self.stop = True

for _a in range(3000):
    self.changeLabel('_a= '+ str(_a))    
    if self.stop:
        self.stop = False
        break

def changeLabel(self,_text):
    self.ui.STATUS.setText(_text)   <---ui is a GUI where label is placed. 
    APP.processEvents()
于 2011-09-09T10:57:33.220 に答える
-1

この問題に対する私の解決策を示したいと思います。

PyQt を使用してセンサーからリアルタイムの写真を撮るためのループを作成しているときに、同様の問題が発生しました。

QTimer を使用することが私にとって唯一の有効な解決策であることがわかりました.yield 1を試し、self.stop is True をチェックしました。

このスレッドは非常に古いため、ここで公開されているものと非常によく似た別の例を使用します。

ある種の信号 (この場合はキーストローク) でカウンターを開始し、別のキーストロークでそれを停止したいと考えています。

このオブジェクトを使用して、Timer によって発行されるシグナルQTimer中にカウンターをアップグレードします。timeout()

class MyExample(QObject):

    timer = QTimer()
    cont = 0

    def __init__(self):

        super(QObject, self).__init__()

        # !!! IMPORTANT PART !!!
        # Here we connect the timeout of the timer to the count
        # function!
        self.timer.timeout.connect(self.cont)

    def keyEvent(self, e):

        # Here we connect the keystroke to the event 
        # on the object!
        if e.key() == Qt.Key_B:

            self.start()

        elif e.key() == Qt.Key_S:

            self.stop()

    def start(self):
        # Number of milliseconds the timer waits until the timeout
        self.timer.start(1000)

    def stop(self):
        self.timer.stop()

    def count(self):
        # Increase the counter on timeout
        self.cont = self.cont + 1
        print self.cont

少なくとも私にとっては、これはうまくいきました!これが誰かを助けたことを願っています!

于 2015-10-26T18:31:27.347 に答える