For loop Tkinter GUI在单击或移动鼠标时不响应(for循环)

For loop Tkinter GUI在单击或移动鼠标时不响应(for循环),for-loop,tkinter,python-multithreading,For Loop,Tkinter,Python Multithreading,我刚刚编写了一个简单的自动化程序来使用TkinterGUI进行测试。 其他一切都很好,除了当我有移动或单击鼠标等操作时,GUI不会响应,但代码仍在运行。循环完成后,GUI进入正常状态。这是我的部分代码(仅用于循环,例如,对于硬件设置和采集,我的代码有点长。) 在循环之外,我已经初始化了文本值和进度条值。我在网上搜索教程,找到了两个解决方案。一个是使用多线程,另一个是使用after函数。但是,当我只有run按钮时,会发生其他触发事件时使用它们。之后,我只想更新每次运行的文本值和进度条值,直到结束。

我刚刚编写了一个简单的自动化程序来使用TkinterGUI进行测试。 其他一切都很好,除了当我有移动或单击鼠标等操作时,GUI不会响应,但代码仍在运行。循环完成后,GUI进入正常状态。这是我的部分代码(仅用于循环,例如,对于硬件设置和采集,我的代码有点长。)


在循环之外,我已经初始化了文本值和进度条值。我在网上搜索教程,找到了两个解决方案。一个是使用多线程,另一个是使用after函数。但是,当我只有run按钮时,会发生其他触发事件时使用它们。之后,我只想更新每次运行的文本值和进度条值,直到结束。谁能给我一些建议吗?多谢各位

这里发生的事情是,您阻止GUI注册事件,因为它太忙了,无法执行代码。您想要的是运行一次代码迭代,然后在重试之前将控制权返回到GUI 5毫秒,而不仅仅是休眠整个线程。请尝试以下操作:

def perform_loop(self, remaining):
    if remaining < 0: return

    power_supply = str(input.iloc[i][0]).split(',')
    channel1 = int(power_supply[0])
    voltage1 = float(power_supply[1])
    current1 = power_supply[2]
    self.power_channel_text.delete(1.0, END)
    self.power_channel_text.insert(1.0, channel1)
    self.voltage_text.delete(1.0, END)
    self.voltage_text.insert(1.0, voltage1)
    self.current_compliance_text.delete(1.0, END)
    self.current_compliance_text.insert(1.0, current1)

    Aardvark = str(input.iloc[i][2]).split(',')
    register_values = []
    start_address = Aardvark[0]
    for n in range(0, len(Aardvark[1].split(' '))):
        register_values.append(int(Aardvark[1].split(' ')[n], 16))
    self.aardvark_write_Address_text.delete(1.0, END)
    self.aardvark_write_Address_text.insert(1.0, start_address)
    self.aardvark_i2c_write_value_text.delete(1.0, END)
    self.aardvark_i2c_write_value_text.insert(1.0, str(Aardvark[1]))

    temp = str(input.iloc[i][3]); save_path = str(input.iloc[i][4])
    self.temperature_text.delete(1.0, END)
    self.temperature_text.insert(1.0, temp)
    self.save_path_text.delete(1.0, END)
    self.save_path_text.insert(1.0, save_path)
    part = str(input.iloc[i][5]); Label = str(input.iloc[i][6])  
    self.progress_bar['value'] = 5 + step * (i + 1)
    self.root.update_idletasks()
    self.root.after(5, lambda x: self.perform_loop(remaining - 1))
def执行_循环(自循环,剩余循环):
如果剩余<0:返回
电源=str(input.iloc[i][0]).split(“,”)
通道1=int(电源[0])
电压1=浮动(电源[1])
电流1=电源[2]
self.power\u channel\u text.delete(1.0,结束)
self.power\u channel\u text.insert(1.0,channel1)
自电压文本删除(1.0,结束)
自电压\文本插入(1.0,电压1)
self.current\u compliance\u text.delete(1.0,结束)
self.current\u compliance\u text.insert(1.0,current1)
Aardvark=str(input.iloc[i][2]).split(“,”)
寄存器_值=[]
起始地址=土豚[0]
对于范围(0,len)中的n(土豚[1]。拆分(“”)):
寄存器_values.append(int(Aardvark[1].split(“”)[n],16))
self.aardvark\u write\u Address\u text.delete(1.0,结束)
self.aardvark\u write\u Address\u text.insert(1.0,起始地址)
self.aardvark\u i2c\u write\u value\u text.delete(1.0,结束)
self.aardvark\u i2c\u write\u value\u text.insert(1.0,str(aardvark[1]))
temp=str(input.iloc[i][3]);save_path=str(input.iloc[i][4])
self.temperature\u text.delete(1.0,结束)
自身温度\文本插入(1.0,温度)
self.save\u path\u text.delete(1.0,结束)
self.save_path_text.insert(1.0,save_path)
part=str(input.iloc[i][5]);Label=str(input.iloc[i][6])
进度条['value']=5+步骤*(i+1)
self.root.update_idletasks()
self.root.after(5,lambda x:self.perform_循环(剩余-1))

然后,在GUI上调用
mainloop
之前,只需调用
perform\u loop
,输入您要执行的迭代次数。

这里发生的情况是,您阻止GUI注册事件,因为它太忙于执行代码。您想要的是运行一次代码迭代,然后在重试之前将控制权返回到GUI 5毫秒,而不仅仅是休眠整个线程。请尝试以下操作:

def perform_loop(self, remaining):
    if remaining < 0: return

    power_supply = str(input.iloc[i][0]).split(',')
    channel1 = int(power_supply[0])
    voltage1 = float(power_supply[1])
    current1 = power_supply[2]
    self.power_channel_text.delete(1.0, END)
    self.power_channel_text.insert(1.0, channel1)
    self.voltage_text.delete(1.0, END)
    self.voltage_text.insert(1.0, voltage1)
    self.current_compliance_text.delete(1.0, END)
    self.current_compliance_text.insert(1.0, current1)

    Aardvark = str(input.iloc[i][2]).split(',')
    register_values = []
    start_address = Aardvark[0]
    for n in range(0, len(Aardvark[1].split(' '))):
        register_values.append(int(Aardvark[1].split(' ')[n], 16))
    self.aardvark_write_Address_text.delete(1.0, END)
    self.aardvark_write_Address_text.insert(1.0, start_address)
    self.aardvark_i2c_write_value_text.delete(1.0, END)
    self.aardvark_i2c_write_value_text.insert(1.0, str(Aardvark[1]))

    temp = str(input.iloc[i][3]); save_path = str(input.iloc[i][4])
    self.temperature_text.delete(1.0, END)
    self.temperature_text.insert(1.0, temp)
    self.save_path_text.delete(1.0, END)
    self.save_path_text.insert(1.0, save_path)
    part = str(input.iloc[i][5]); Label = str(input.iloc[i][6])  
    self.progress_bar['value'] = 5 + step * (i + 1)
    self.root.update_idletasks()
    self.root.after(5, lambda x: self.perform_loop(remaining - 1))
def执行_循环(自循环,剩余循环):
如果剩余<0:返回
电源=str(input.iloc[i][0]).split(“,”)
通道1=int(电源[0])
电压1=浮动(电源[1])
电流1=电源[2]
self.power\u channel\u text.delete(1.0,结束)
self.power\u channel\u text.insert(1.0,channel1)
自电压文本删除(1.0,结束)
自电压\文本插入(1.0,电压1)
self.current\u compliance\u text.delete(1.0,结束)
self.current\u compliance\u text.insert(1.0,current1)
Aardvark=str(input.iloc[i][2]).split(“,”)
寄存器_值=[]
起始地址=土豚[0]
对于范围(0,len)中的n(土豚[1]。拆分(“”)):
寄存器_values.append(int(Aardvark[1].split(“”)[n],16))
self.aardvark\u write\u Address\u text.delete(1.0,结束)
self.aardvark\u write\u Address\u text.insert(1.0,起始地址)
self.aardvark\u i2c\u write\u value\u text.delete(1.0,结束)
self.aardvark\u i2c\u write\u value\u text.insert(1.0,str(aardvark[1]))
temp=str(input.iloc[i][3]);save_path=str(input.iloc[i][4])
self.temperature\u text.delete(1.0,结束)
自身温度\文本插入(1.0,温度)
self.save\u path\u text.delete(1.0,结束)
self.save_path_text.insert(1.0,save_path)
part=str(input.iloc[i][5]);Label=str(input.iloc[i][6])
进度条['value']=5+步骤*(i+1)
self.root.update_idletasks()
self.root.after(5,lambda x:self.perform_循环(剩余-1))

然后在GUI上调用
mainloop
之前,只需调用
perform\u loop
,输入您想要执行的迭代次数。

很抱歉再次打扰您,我发现我的while代码存在一些问题。我确实需要在for循环中进行一些延迟,以等待硬件进行采集或计算。我的理解是现在我不能用time.sleep方法来做延迟。或者只是在更新GUI的过程中,我不能使用time.sleep,在这些代码片段之后或之前,我仍然能够避免延迟。非常感谢。如果您想在任何地方使用
time.sleep()
,请将它下面的代码拆分为一个新的定义,然后在(,)之后使用sleep调用
self.root.after。您的代码在时间段之后才会被调用,与您使用睡眠时完全相同,但它将允许GUI在该时间内更新,这正是您想要的。再次感谢您,我修改了代码。99.9%正在工作,但是,在我的代码中,我需要从作用域获取数据,在此期间,GUI将无论如何冻结。虽然循环可能会发生1秒,但我仍然想知道是否有办法解决这个问题?像多线程?它比root.after方案更复杂。我在网上看了一些教程,已经知道了基本知识。我仍然不知道如何用线程实现我的代码。有什么建议吗