我目前正在编写我的第一个tkinter图形用户界面.我正在try 制作一个交互式绘图,使用一些比例,以便用户可以设置影响该绘图的参数值.当我这样做时,它开始滞后,并且我的解决方案;使用线程的工作并不像预期的那样工作.
在我的实际代码中,有多个绘图,因此应用程序开始滞后,如下所示:
from tkinter import *
from tkinter import ttk
import threading
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import time
import numpy as np
def create_window(root):
frame1 = Frame(root)
frame2 = Frame(root)
frame1.grid(row=0,column=0)
frame2.grid(row=0,column=1)
figure1 = plt.Figure(figsize=(5,5))
figure1.set_tight_layout(True)
ax1 = figure1.add_subplot(111)
canvas1 = FigureCanvasTkAgg(figure1, frame1)
canvas1.get_tk_widget().grid(column=1,row=1, padx=10, pady=10)
m.trace_add('write', lambda var=None, index=None, mode=None: update_plot_tracer(ax1, canvas1))
m_scale = ttk.Scale(frame2, orient=VERTICAL, length=200, from_=100.0, to=0.0, variable=m)
m_scale.grid(column=0, row=0)
update_plot(ax1,canvas1)
def update_plot(ax, canvas):
#to make it lag
time.sleep(0.1)
x = np.arange(0,10,1)
y = m.get() * x
ax.clear()
ax.plot(x,y)
ax.set_ylim([0, 100])
canvas.draw()
def update_plot_tracer(ax, canvas, var=None, index=None, mode=None):
update_plot(ax, canvas)
if __name__ == '__main__':
root = Tk()
m = DoubleVar(value = 10.0)
create_window(root)
root.mainloop()
我的解决方案是使用线程,以便在绘制绘图时用户界面的其余部分仍然可用.我现在遇到的问题是,当用户大量拖动比例时,会有多个线程调用,这些线程会干扰我,所以我试图阻止程序同时多次更新,如下所示:
from tkinter import *
from tkinter import ttk
import threading
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import time
import numpy as np
def create_window(root):
frame1 = Frame(root)
frame2 = Frame(root)
frame1.grid(row=0,column=0)
frame2.grid(row=0,column=1)
figure1 = plt.Figure(figsize=(5,5))
figure1.set_tight_layout(True)
ax1 = figure1.add_subplot(111)
canvas1 = FigureCanvasTkAgg(figure1, frame1)
canvas1.get_tk_widget().grid(column=1,row=1, padx=10, pady=10)
m.trace_add('write', lambda var=None, index=None, mode=None: update_plot_tracer(ax1, canvas1))
m_scale = ttk.Scale(frame2, orient=VERTICAL, length=200, from_=100.0, to=0.0, variable=m)
m_scale.grid(column=0, row=0)
update_plot(ax1,canvas1)
m_entry = ttk.Entry(frame2, textvariable = m)
m_entry.grid(column=0, row=1)
def update_plot(ax, canvas):
x = np.arange(0,10,1)
y = m.get() * x
print('last used value of m', m.get())
ax.clear()
ax.plot(x,y)
ax.set_ylim([0, 100])
canvas.draw()
#to make it lag
time.sleep(0.2)
def update_plot_tracer(ax, canvas, var=None, index=None, mode=None):
global thread1#just to make this example work, in my real code i have it as a class variable...
if thread1 is None or not thread1.is_alive():
thread1 = threading.Thread(target= lambda: update_plot(ax, canvas))
thread1.start()
if __name__ == '__main__':
thread1 = None
root = Tk()
m = DoubleVar(value = 10.0)
create_window(root)
root.mainloop()
现在我有了下一个问题:当线程启动但用户不断移动鼠标时,他/她看到的值不是绘图中使用的值,所以我想做一些类似向队列添加线程的操作,但然后我会遇到这个队列可能会变得非常长的问题,而且需要一些时间才能更新到最新状态,即使当前运行的线程和最新添加的线程之间的所有线程都没有用,但据我所知,一旦我向队列添加了线程(从队列围栏),它就不能被删除.我从来没有用过这方面的大部分工作,所以任何帮助都是感激的.
此外,我想让它尽可能地保持互动性,所以只在用户松开天平后才更新不是我的首选方式.
编辑:问题是如何创建可以从中删除条目的线程队列?