[英]Multithreading in tkinter using window.after
I'm having a rough time trying to create threads inside a tkinter GUI.我在尝试在 tkinter GUI 中创建线程时遇到了困难。 To give some background on what I would like the code to do.
提供一些关于我希望代码做什么的背景。 This is a GUI that when the log buttons are pressed (eg
log_1
).这是一个 GUI,当按下日志按钮时(例如
log_1
)。 I'd like to send a continuous command to fire a laser and eventually (after I tackle the current problem) log the subsequent parameters.我想发送一个连续的命令来发射激光并最终(在我解决当前问题之后)记录后续参数。
However, my issue is that I have 5 lasers needing to be fired at the same time (or very close to) and the more lasers I have in the logging state ON the more the time delay between the lasers firing.但是,我的问题是我需要同时(或非常接近)发射 5 个激光器,并且处于记录状态 ON 的激光器越多,激光器发射之间的时间延迟就越长。 I guess this is an issue because my:
fire_all()
function in conjunction with the window after(100, fire_all)
is not a threaded process so having more lasers firing results in more of a time delay between the onset of the command to fire.我想这是一个问题,因为我的:
fire_all()
函数与window after(100, fire_all)
不是一个线程过程,所以有更多的激光发射会导致发射命令开始之间的时间延迟更多。
My code is below.我的代码如下。 Does anyone have any suggestions how to implement this properly?
有没有人有任何建议如何正确实施?
# start the GUI
import tkinter as tk
window = tk.Tk()
def fire_astrum(dev): # N = 100 # no of points in stream array, pulse_count = int(1) # no of desired pulses in pulse train #command is command volatge
#dev,ana_out,ana_in,N,pulse_count,pulse_on,pulse_off,command
#dev = 'Dev1'
ana_out = 'ao0'
ana_in = "ai0:1"# for non consecutive channels use: "Dev0/ai0:Dev0/ai4"
N = 100
pulse_count = 10
pulse_on = 45
pulse_off = 15
command = 3.5
channel = dev +'/' + ana_out
tot = dev + "/" + ana_in
duty = pulse_on/(pulse_on+pulse_off) # duty cycle in %
array_on = int(N*duty) # on values in array
array_off = int(N-array_on) # off values in array
samples = np.append(command*np.ones(array_on),np.zeros(array_off)) # command is command voltage (IPROG), sets up stream array to send to NI box
curr = np.empty((2,pulse_count*len(samples))) # Empty arrays for IMON,VMON
error = np.uint32(np.empty((3,pulse_count*len(samples)))) # # Empty arrays for Digital inputs with pull-up resistors (READY, ERR1 & ERR2)
#sample_clock = '/'+dev+'/ai/SampleClock'
arm_laser(dev,'on') # Sends 5V to Astrum to arm laser diode
time.sleep(0.3) # wait for 300ms before data stream
with nidaqmx.Task() as writeTask, nidaqmx.Task() as readcurr, nidaqmx.Task(): # as digitalread:#, nidaqmx.Task() as readvolt:
writeTask.ao_channels.add_ao_voltage_chan(channel,units = Volts)
writeTask.ao_channels.all.ao_max = 4 # Hard clamp Limit to 4V to protect laser diode
writeTask.ao_channels.all.ao_min = 0 # Set baseline to 0V (ground loop protection)
readcurr.ai_channels.add_ai_voltage_chan(tot, units = Volts,terminal_config = TerminalConfiguration.RSE) # define differntial NRE connfig of channels
#print(read_curr.ai_term_cfg)
#digitalread.di_channels.add_di_chan(dev + '/port0/line0:2',line_grouping=LineGrouping.CHAN_PER_LINE)
#writeTask.triggers.start_trigger.cfg_dig_edge_start_trig('/' + dev +'/' + terminal) #Setting the trigger on the analog input
writeTask.timing.cfg_samp_clk_timing(rate=(array_on/N)*1/pulse_on*1000*N,sample_mode= nidaqmx.constants.AcquisitionType.FINITE , samps_per_chan= pulse_count*len(samples))
readcurr.timing.cfg_samp_clk_timing(rate=(array_on/N)*1/pulse_on*1000*N, sample_mode= nidaqmx.constants.AcquisitionType.FINITE , samps_per_chan= pulse_count*len(samples))
#digitalread.timing.cfg_samp_clk_timing(rate=(array_on/N)*1/pulse_on*1000*N, sample_mode= nidaqmx.constants.AcquisitionType.FINITE , samps_per_chan= pulse_count*len(samples))
reader_curr = AnalogMultiChannelReader(readcurr.in_stream)
#digital = DigitalMultiChannelReader(digitalread.in_stream)
writer = AnalogSingleChannelWriter(writeTask.out_stream, auto_start=True)
writer.write_many_sample(samples)
time_vec = np.linspace(0, (pulse_on+pulse_off)*pulse_count, num=len(curr[0]), endpoint=True)
reader_curr.read_many_sample(data = curr,number_of_samples_per_channel = pulse_count*len(samples), timeout = nidaqmx.constants.WAIT_INFINITELY)# read from DAQ
#digital.read_many_sample_port_uint32(data = error,number_of_samples_per_channel = pulse_count*len(samples), timeout = nidaqmx.constants.WAIT_INFINITELY)# read from DAQ
curr = np.around(curr, 6) # Round all values to 6 decimals to avoid overflow
error = np.around(error, 6) # Round all values to 6 decimals to avoid overflow
print("The channels linked to WriteTask are: ")
for i in writeTask.ao_channels:
print(i)
print("The channels linked to ReadTask are: ")
for j in readcurr.ai_channels:
print(j)
################# Astrum parameters #########################
imon = curr[0]
vmon = curr[1]
ready = error[0]
err1 = error[1]
err2 = error[2]
trigger = np.tile(samples,pulse_count)
###############################################################
arm_laser(dev,'off')
###############################################################
V = np.max(vmon)
I = np.max(imon)
#for j in range(9):
laser_1[6].config(text = V)
laser_1[7].config(text = I)
def log1():
if log_1.config('text')[-1] =='ON':
log_1.config(text='OFF', bg="red",activebackground="red",textvariable=0)
print(log_1.config('textvariable')[-1])
else:
log_1.config(text='ON', bg="green",activebackground="green",textvariable=1)
print(log_1.config('textvariable')[-1])
def log2():
if log_2.config('text')[-1] =='ON':
log_2.config(text='OFF', bg="red",activebackground="red",textvariable=0)
print(log_2.config('textvariable')[-1])
else:
log_2.config(text='ON', bg="green",activebackground="green",textvariable=1)
print(log_2.config('textvariable')[-1])
def log3():
if log_3.config('text')[-1] =='ON':
log_3.config(text='OFF', bg="red",activebackground="red",textvariable=0)
print(log_3.config('textvariable')[-1])
else:
log_3.config(text='ON', bg="green",activebackground="green",textvariable=1)
print(log_3.config('textvariable')[-1])
def log4():
if log_4.config('text')[-1] =='ON':
log_4.config(text='OFF', bg="red",activebackground="red",textvariable=0)
print(log_4.config('textvariable')[-1])
else:
log_4.config(text='ON', bg="green",activebackground="green",textvariable=1)
print(log_4.config('textvariable')[-1])
def log5():
if log_5.config('text')[-1] =='ON':
log_5.config(text='OFF', bg="red",activebackground="red",textvariable=0)
print(log_5.config('textvariable')[-1])
else:
log_5.config(text='ON', bg="green",activebackground="green",textvariable=1)
print(log_5.config('textvariable')[-1])
##### logging button lasers ###########
log_1 = tk.Button(top_frame, width=8 , bd=4, text = 'OFF', command = log1, bg = "red")
log_1.grid(row = 2, column = 8)
log_2 = tk.Button(top_frame, width=8 , bd=4, text = 'OFF', command = log2, bg = "red") #, onvalue=1, offvalue=0)
log_2.grid(row = 3, column = 8)
log_3 = tk.Button(top_frame, width=8 , bd=4, text = 'OFF', command = log3, bg = "red") #, onvalue=1, offvalue=0)
log_3.grid(row = 4, column = 8)
log_4 = tk.Button(top_frame, width=8 , bd=4, text = 'OFF', command = log4, bg = "red") #, onvalue=1, offvalue=0)
log_4.grid(row = 5, column = 8)
log_5 = tk.Button(top_frame, width=8 , bd=4, text = 'OFF', command = log5, bg = "red") #, onvalue=1, offvalue=0)
log_5.grid(row = 6, column = 8)
def fire_all():
#global a
a = str(log_1.config('textvariable')[-1])
b = str(log_2.config('textvariable')[-1])
c = str(log_3.config('textvariable')[-1])
d = str(log_4.config('textvariable')[-1])
e = str(log_5.config('textvariable')[-1])
if a == '1':
fire_astrum('Dev1')
if b == '1':
fire_astrum('Dev2')
if c == '1':
fire_astrum('Dev3')
if d == '1':
fire_astrum('Dev4')
if e == '1':
fire_astrum('Dev5')
# call this function again in 100 milliseconds
window.after(100, fire_all)
window.after(100, fire_all)
window.mainloop()
you can probably launch fire_astrum
in a thread from fire_all
.你或许可以推出
fire_astrum
从一个线程fire_all
。
maybe like this:也许是这样的:
import threading
...
if a == '1':
threading.Thread(target=lambda dev='Dev1': fire_astrum(dev)).start()
...
It is unclear how long fire_astrum
takes to complete;目前还不清楚
fire_astrum
需要多长时间才能完成; it also sleeps for 300ms;它还休眠 300 毫秒; there is no telling the outcome when fired every 100ms, you'll have to try.
每 100 毫秒触发一次时无法知道结果,您必须尝试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.