Остановить непрерывно работающие функции tkinter без закрытия GUI - PullRequest
0 голосов
/ 17 мая 2018

Я пытался сделать несколько разных вещей, чтобы остановить этот код (после [не останавливает его], выйти [закрывает GUI]).То, что я обнаружил, что "сработало", это выброс ошибки ..... Это беспокоит меня.Сгенерировать ошибку, а затем просто перезапустить график не идеально.Я хочу очистить этот код (поэтому любые другие предложения также приветствуются!)

Я что-то упустил?Разве остановка функции не должна быть простой?Я опубликую основной код, который еще много, так как есть много функций.Два, которые я хочу остановить (основываясь на том, что распечатывается) - это update_graph и get_data.Если я говорю, что я хочу 5 файлов, он получает 5 файлов (i = 5), а затем перезапускается с 0 (i = 0).

Что должен делать код:

Сначала в графическом интерфейсе отображается пустой график.Человек может установить количество файлов, которые он хочет иметь, и настроить время интеграции датчика.Затем они могут начать сбор данных, и график всплывает каждую секунду или около того, пока не будет достигнуто количество файлов.Эта последняя часть - то, чего я не могу получить.Остановка создания файла и построения графиков при достижении количества файлов.(Примечание: создание файла совершенно в другом коде. Я только показываю этот код, чтобы не создавать тонну файлов, устраняющих неполадки с этим).

try:
    import Tkinter as tk
except ImportError:
    import tkinter as tk
from PIL import ImageTk, Image
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from matplotlib import pyplot as plt
import matplotlib.animation as animation
import serial
import random
import os
import datetime
import numpy as np
after_id = None

def get_data():
    #i=0

    rand_x = list(range(100))
    rand_y = [random.randrange(100) for _ in range(100)]
        #create a file

## In my code, this function send data through serial port from the Raspberry pi to the arduino and the arduino send the y axis data back.
##I then create the appropriate x axis
    return rand_x, rand_y


class App(tk.Frame):
    def __init__ (self, master=None, **kwargs):
        tk.Frame.__init__(self, master, **kwargs)
        self.running = False
        self.ani = None
        btns = tk.Frame(self)
        btns.pack()
        lbl = tk.Label(btns, text="Number of times to run")
        lbl.pack(side=tk.LEFT)
        self.points_ent = tk.Entry(btns, width=5)
        self.points_ent.insert(0,'50')
        self.points_ent.pack(side=tk.LEFT)
        lbl = tk.Label(btns, text="Intergration Time")
        lbl.pack(side=tk.LEFT)
        self.interval = tk.Entry(btns, width=5)
        self.interval.insert(0, '100')
        self.interval.pack(side=tk.LEFT)
        self.btn = tk.Button(btns, text='Start', command=self.on_click)
        self.btn.pack(side=tk.LEFT)
        self.fig = plt.Figure()
        self.ax1 = self.fig.add_subplot(111)
        self.line, = self.ax1.plot([], [], lw=2)
        self.canvas = FigureCanvasTkAgg(self.fig, master=self)
        self.canvas.show()
        self.canvas.get_tk_widget().pack()
        self.ax1.set_ylim(0, 500)
        self.ax1.set_xlim(0, 100)

    def on_click(self):

        print('onclick')
        if self.ani is None:
            return self.start()

        if self.running:
            self.ani.event_source.stop()
            self.btn.config(text='Un-Pause')
            print('pause')
        else:

            self.ani.event_source.start()
            self.btn.config(text='Pause', command=get_data())
            print('unpause')
        self.running = not self.running

    def start(self):
        global interval
        self.points = int(self.points_ent.get()) + 1
        print(self.points)
        self.ani = animation.FuncAnimation(
            self.fig, self.update_graph,
            frames=self.points,
            interval=int(self.interval.get()),
            repeat=True)
        self.running = True
        self.btn.config(text='Pause')
        self.ani._start()
        print('started animation')

    def update_graph(self, i):
        while os.path.exists(str(directory) + "/Data" + str(i) + "/"):
            i +=1
        subfolder = (str(directory) + "/Data" + str(i) + "/")
        global filename
        filename = "/home/pi/Documents/Serial" + str(i) + ".txt"
        self.line.set_data(*get_data())
        print('update_graph')
        print(i)
        global after_id
        after_id = self.after(1, get_data)
        if i >= self.points - 1:

            self.running = False
            self.ani = None
            self.btn.config(text='Start', command=self.stop())


    def stop(self):
        global after_id
        self.after_cancel(after_id)

1 Ответ

0 голосов
/ 17 мая 2018

Я думаю, что вам не хватает одного очень важного утверждения в вашей функции update_graph, и вы много пытались с after и изменением команд кнопок, чтобы попытаться исправить это.

Что вам не хватает в update_graph, так это просто self.ani._stop(), чтобы остановить анимацию при достижении желаемого количества итераций.

Итак, вставив это и удалив все вызовы after, которые, я думаю, не принесли пользы, оставив одну только кнопку, я пришел к этому, что, я чувствую, делает именно то, что вы хотите:

try:
    import Tkinter as tk
except ImportError:
    import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from matplotlib import pyplot as plt
import matplotlib.animation as animation
import random

def get_data():
    #i=0

    rand_x = list(range(100))
    rand_y = [random.randrange(100) for _ in range(100)]
        #create a file

## In my code, this function send data through serial port from the Raspberry pi to the arduino and the arduino send the y axis data back.
##I then create the appropriate x axis
    return rand_x, rand_y


class App(tk.Frame):
    def __init__ (self, master=None, **kwargs):
        tk.Frame.__init__(self, master, **kwargs)
        self.running = False
        self.ani = None
        btns = tk.Frame(self)
        btns.pack()
        lbl = tk.Label(btns, text="Number of times to run")
        lbl.pack(side=tk.LEFT)
        self.points_ent = tk.Entry(btns, width=5)
        self.points_ent.insert(0,'50')
        self.points_ent.pack(side=tk.LEFT)
        lbl = tk.Label(btns, text="Intergration Time")
        lbl.pack(side=tk.LEFT)
        self.interval = tk.Entry(btns, width=5)
        self.interval.insert(0, '100')
        self.interval.pack(side=tk.LEFT)
        self.btn = tk.Button(btns, text='Start', command=self.on_click)
        self.btn.pack(side=tk.LEFT)
        self.fig = plt.Figure()
        self.ax1 = self.fig.add_subplot(111)
        self.line, = self.ax1.plot([], [], lw=2)
        self.canvas = FigureCanvasTkAgg(self.fig, master=self)
        self.canvas.show()
        self.canvas.get_tk_widget().pack()
        self.ax1.set_ylim(0, 500)
        self.ax1.set_xlim(0, 100)

    def on_click(self):

        print('onclick')
        if self.ani is None:
            return self.start()

        if self.running:
            self.ani.event_source.stop()
            self.btn.config(text='Un-Pause')
            print('pause')
        else:

            self.ani.event_source.start()
            self.btn.config(text='Pause')
            print('unpause')
        self.running = not self.running

    def start(self):
        self.points = int(self.points_ent.get()) + 1
        print(self.points)
        self.ani = animation.FuncAnimation(
            self.fig, self.update_graph,
            frames=self.points,
            interval=int(self.interval.get()),
            repeat=True)
        self.running = True
        self.btn.config(text='Pause')
        self.ani._start()
        print('started animation')

    def update_graph(self, i):
        self.line.set_data(*get_data())
        print('update_graph')
        print(i)
        if i >= self.points - 1:

            self.running = False
            self.ani._stop()
            self.ani = None
            self.btn.config(text='Start')


root = tk.Tk()
app = App(root)
app.pack(expand=1, fill=tk.BOTH)
root.mainloop()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...