我正在创建一个GUI,允许用户查看分光仪的“实时视图”,其中数据从分光仪中获取并在Matplotlib中绘制以显示在GUI窗口中。 GUI还有一些其他按钮,允许用户通过其他功能(不相关但只是背景)。
我使用while循环和清除数据重新绘制,在Matplotlib中已使实时视图工作:
while True:
data = ccs.take_data(num_avg=3) # spectrometer function
norm = (data[0]-dark[0])/(light[0]-dark[0]) # some calcs.
plt.plot(data[1],norm)
plt.axis([400,740,0,1.1])
plt.grid(color='w', linestyle='--')
plt.xlabel('Wavelength [nm]')
plt.ylabel('Normalized Intesity')
plt.pause(0.1)
plt.cla()
下一步是在PySimpleGUI中展示这张图表。比预想的难...我能够使用一些来自PySimpleGUI的演示代码,让单个图表出现并且如果用户按下“更新”按钮也能够更新:
from instrumental.drivers.spectrometers import thorlabs_ccs
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import PySimpleGUI as sg
import matplotlib, time, threading
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
def fig_maker(ccs, dark, sub):
plt.clf()
plt.close()
data = ccs.take_data(num_avg=3)
norm = (data[0]-dark[0])/(sub[0]-dark[0])
plt.plot(data[1],norm,c='r')
plt.axis([400,750,0,1.1])
plt.grid(color='w', linestyle='--')
plt.xlabel('Wavelength [nm]')
plt.ylabel('Normalized Intesity')
return plt.gcf()
def draw_figure(canvas, figure, loc=(0, 0)):
figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
figure_canvas_agg.draw()
figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
return figure_canvas_agg
def delete_fig_agg(fig_agg):
fig_agg.get_tk_widget().forget()
plt.close('all')
if __name__ == '__main__':
... some code ...
# define the window layout
layout = [[sg.Button('update')],
[sg.Text('Plot test', font='Any 18')],
[sg.Canvas(size=(500,500), key='canvas')] ]
# create the form and show it without the plot
window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI',
layout, finalize=True)
fig_agg = None
while True:
event, values = window.read()
if event is None: # if user closes window
break
if event == "update":
if fig_agg is not None:
delete_fig_agg(fig_agg)
fig = fig_maker(ccs,dark,sub)
fig_agg = draw_figure(window['canvas'].TKCanvas, fig)
window.close()
现在是有趣的部分(我似乎无法让它工作)。我希望绘图始终更新,类似于我只使用matplotlib时所做的那样,以便用户不必按“更新”按钮。使用PySimpleGUI长时间任务多线程示例是我的程序开始失败的地方。实际上,除了向Debug I/O打印***模拟超时***之外,我没有收到任何错误提示,然后Python关闭脚本。
我甚至尝试做一个10次迭代的for循环而不是连续的while循环:
from instrumental.drivers.spectrometers import thorlabs_ccs
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import PySimpleGUI as sg
import matplotlib, time, threading
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
def long_function_thread(window, ccs, dark, sub):
for i in range(10):
fig = fig_maker(ccs, dark, sub)
fig_agg = draw_figure(window['canvas'].TKCanvas, fig)
window.write_event_value('-THREAD PROGRESS-', i)
time.sleep(1)
delete_fig_agg(fig_agg)
time.sleep(0.1)
window.write_event_value('-THREAD DONE-', '')
def long_function(window, ccs, dark, sub):
print('In long_function')
threading.Thread(target=long_function_thread, args=(window, ccs, dark, sub), daemon=True).start()
def fig_maker(ccs, dark, sub):
plt.clf()
plt.close()
data = ccs.take_data(num_avg=3)
norm = (data[0]-dark[0])/(sub[0]-dark[0])
plt.plot(data[1],norm,c='r')
plt.axis([400,750,0,1.1])
plt.grid(color='w', linestyle='--')
plt.xlabel('Wavelength [nm]')
plt.ylabel('Normalized Intesity')
return plt.gcf()
def draw_figure(canvas, figure, loc=(0, 0)):
figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
figure_canvas_agg.draw()
figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
return figure_canvas_agg
def delete_fig_agg(fig_agg):
fig_agg.get_tk_widget().forget()
plt.close('all')
if __name__ == '__main__':
... some code ...
# define the window layout
layout = [[sg.Button('Go')],
[sg.Text('Plot test', font='Any 18')],
[sg.Canvas(size=(500,500), key='canvas')] ]
# create the form and show it without the plot
window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI',
layout, finalize=True)
fig_agg = None
while True:
event, values = window.read()
if event is None or event == 'Exit':
break
if event == 'Go':
print('Calling plotter')
long_function(window, ccs, dark, sub)
print('Long function has returned from starting')
elif event == '-THREAD DONE-':
print('Your long operation completed')
window.close()
很抱歉这里有些冗长的描述和代码堆积,但我认为这是最容易解释的方式。如果能够在此问题上提供任何帮助或链接,将不胜感激。
如果有人想要运行我的脚本,则应该只会生成一个随机图表。
def random_fig_maker():
plt.scatter(np.random.rand(1,10),np.random.rand(1,10))
return plt.gcf()