簡體   English   中英

Python-從外部函數中斷循環

[英]Python - breaking a loop from an outside function

我想通過使用matplolib某些按鈕來控制某些功能的執行。 我想暫停執行一個函數,在本例中是為了中斷for循環,因為我在腳本中使用了以下命令:

def pause(mouse_event):
    global pauseVal
    pauseVal ^= True

def play(mouse_event):    
    for x in range(int(dataSlider.val),len(listOfMomentsVis)):
        if pauseVal == True:
            break
        else:
            image.set_data(listOfMomentsVis[x]) 
            fig.canvas.draw()
            dataSlider.set_val(x+1)
            time.sleep(timeSleep)
            print(x)

發生的情況是該函數將在下次嘗試執行時而不是在執行期間不執行 換句話說, pause按鈕在下一次執行之前不會生效。

我的問題是:如何通過外部按鈕事件在執行過程中中斷for循環? 那可行還是應該采用其他方式? (可以讓for循環listen外部函數嗎?!)

PS:我發現了以下標題相同的問題,即如何從外部函數中斷循環 ,但是,答案是根據循環中的值而不是外部值中斷。

updae

這是我的腳本更新版本。 我考慮了評論和答案,做了一堂課,但仍然沒有得到想要的結果。

class animationButtons():
    def __init__(self):
        self.pauseVal = False

    def backward(self, mouse_event):
        ref = int(dataSlider.val)
        if ref-1<0:
            print('error')
        else:
            image.set_data(listOfMomentsVis[ref-1])
            dataSlider.set_val(ref-1)

    def forward(self, mouse_event):
        ref = int(dataSlider.val)
        if ref+1>len(listOfMomentsVis):
            ref = int(dataSlider.val)-1
            print('error')
        else:
            image.set_data(listOfMomentsVis[ref])
            dataSlider.set_val(ref+1)
            print('from forward', dataSlider.val)

    def play(self, mouse_event):
        for x in range(int(dataSlider.val),len(listOfMomentsVis)):
            ref = int(dataSlider.val)
            dataSlider.set_val(ref+1)
            time.sleep(timeSleep)
            print('from play',ref)
            if self.pauseVal:
                break

    def playReverse(self, mouse_event):
        for x in range(int(dataSlider.val),0,-1):
            ref = int(dataSlider.val)
            dataSlider.set_val(ref-1)
            time.sleep(timeSleep)
            print('from play',ref)
            if self.pauseVal:
                break

    def pause(self, mouse_event):
        self.pauseVal ^= True
        print(self.pauseVal)

    def animate(self, val):
        ref = int(dataSlider.val)
        image.set_data(listOfMomentsVis[ref])
        print('from animate',ref)
        fig.canvas.draw()

來自GUI事件處理程序的回調應快速完成,否則它們將占用負責處理事件的線程。 這意味着您不能在回調函數中time.sleep(timeSleep)

相反,您可以使用計時器來定期觸發動畫事件,然后使用播放和暫停按鈕來停止和啟動計時器。 下面的示例創建一個移動的正弦波,該正弦波在移動了一個完整波長后會停止。 如果尚未播放動畫,則按下播放會觸發動畫;如果當前正在暫停動畫,則繼續播放。 如果正在播放動畫,則暫停將暫停動畫。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button

fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.2) # add space for buttons

x = np.arange(0, 2*np.pi, 0.01)
line, = ax.plot(x, np.sin(x))

class Example:

    steps = 200

    def __init__(self):
        self.step_index = 0
        self.timer = None

    def animate(self):
        print(self.step_index)
        # update the data
        line.set_ydata(np.sin(x + (2 * np.pi * self.step_index / self.steps)))
        self.step_index += 1
        plt.draw()        

        # stop if end of animation
        if self.step_index >= self.steps:
            self.timer = None
            return False

    def play(self, event):
        if not self.timer:
            # no current animation, start a new one.
            self.timer = fig.canvas.new_timer(interval=10)
            self.timer.add_callback(self.animate)
            self.step_index = 0
        self.timer.start()

    def pause(self, event):
        if not self.timer:
            return
        self.timer.stop()

ex = Example()
ax_pause = plt.axes([0.7, 0.05, 0.1, 0.075])
ax_play = plt.axes([0.81, 0.05, 0.1, 0.075])
pause_button = Button(ax_pause, 'Pause')
pause_button.on_clicked(ex.pause)
play_button = Button(ax_play, 'Play')
play_button.on_clicked(ex.play)

plt.show()

像這樣的事情可能更像是一種面向對象的方法。

class ClasName():
    # Add any variables you want to keep track of...
    def __init__(self, dataSlider, listOfMomentsVis):
        self.paseVal = False
        self.dataSlider = dataSlider
        self.listOfMomentsVis = listOfMomentsVis 

    # Your methods to manipulate the class instance variables
    def pause(self, mouse_event):
        self.pauseVal ^= True

    def play(self, mouse_event):    
        for x in range(int(self.dataSlider.val),len(self.listOfMomentsVis)):
            if self.pauseVal == True:
                # Reset the pauseVal state
                self.pauseVal ^= False
                break

            else:
                image.set_data(listOfMomentsVis[x]) 
                fig.canvas.draw()
                dataSlider.set_val(x+1)
                time.sleep(timeSleep)
                print(x)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM