为了账号安全,请及时绑定邮箱和手机立即绑定

Python Tkinter用于模拟多个按钮之间的交互闪烁

Python Tkinter用于模拟多个按钮之间的交互闪烁

慕雪6442864 2021-03-26 15:11:28
我正在寻找一种解决方案,以模拟电子组件的UI行为和带有LED的用户交互(应该是按钮),以报告电子组件的内部状态。我正在使用python和tKinter模块来执行此操作。我的代码运行,并且我的GUI窗口正确显示。但是,当我按几次按钮时,行为不符合预期。每个LED有4种可能的状态(关闭,打开,(闪烁)慢速,(闪烁)快速)。我有4个可以影响状态的按钮。每个按钮都有一个在我定义的小部件类中定义的交互功能,并且一旦调用此功能,每个按钮都会重新定义小部件的内部状态。为了控制LED的闪烁,我使用了一个单循环和self.after(..)函数。该功能如下:def toggleLeds(self):    for led in [self.ledTxIP, self.ledRxIP, self.ledTxRS, self.ledRxRS, self.ledPower, self.ledRun, self.ledStatus, self.ledConfig]:        if (((led[1] == "SLOW") and (self._FastBlinking == 0)) or (led[1] =="FAST")):            bg = led[0].cget("background")            bg = "green" if bg == "black" else "black"            led[0].configure(background=bg)        elif((led[1] == "OFF") and (self._update == 1)):            led[0].configure(background="black")            self._update = 0        elif (self._update == 1):            led[0].configure(background="green")            self._update = 0    self._FastBlinking = (self._FastBlinking + 1)%2    self.update_idletasks()    self.after(self._FastBlinkTime, self.toggleLeds)通过self.after函数递归调用此函数,在交互函数的末尾,我为每个按钮定义了该函数。这是我定义单个LED的方式:    self.ledTxIP     = [tk.Label(self, width=1, borderwidth=2, relief="groove"),"OFF"]以下是按钮交互功能的示例:def pushMode(self):    if (re.search("Reset",self.state) == None):        if (self.clickModCnt == 0):            self.state = "Status"            self._stateTimer = int(time.gmtime()[5])        elif (self.clickModCnt == 1):            if(int(time.gmtime()[5]) - self._stateTimer < 3):                self.state = "Config"            else:                self.state = "RunMode"        else:            self.state = "RunMode"    self.clickModCnt = (self.clickModCnt + 1)%3    self._update = 1    self.updateLedState()如果有人对此有任何建议,那就太受欢迎了。
查看完整描述

1 回答

?
四季花海

TA贡献1811条经验 获得超5个赞

我不知道为什么这没有早点让我明白,但是我认为问题在您自己的问题文本中列出,是指toggleLeds方法:

通过self.after函数递归调用此函数,在交互函数的末尾,我为每个按钮定义了该函数。

程序最初运行时,我假设您在toggleLeds某个地方调用以启动LED的初始模式。这将通过self.after方法末尾的调用来建立单个递归循环。但是,如果您每次单击按钮来更改状态时调用相同的方法,则每次单击按钮都将建立一个新循环,并且每个新循环可能与初始循环同步,也可能不同步。

我可以想到几种方法来解决这种可能的冲突。一种是避免对进行新的调用toggleLeds,但是那样在单击按钮和新的LED模式之间可能会有延迟。如果您不介意延迟,那可能是最好的解决方案。

如果要立即更改灯光/闪烁模式,则需要中断当前循环并以新的灯光/闪烁状态开始一个新的循环。根据New Mexico Tech生产的Tkinter参考,该after方法为:

...返回一个整数“之后标识符”,如果您想取消回调,可以将其传递给.after_cancel()方法。

这就是您可以利用的方法。首先,请确保在调用after方法时存储了该标识符:

self.after_id = self.after(self._FastBlinkTime, self.toggleLeds)

然后更改您的toggleLeds方法定义以接受可选的“ interrupt”参数,after如果该参数为,则取消现有循环True

def toggleLeds(self, interrupt=False):

    if interrupt:

        self.after_cancel(self.after_id)

    # Existing code follows

最后,True在单击按钮后调用方法时传递给该参数:


# Existing button processing code here

self.toggleLeds(interrupt=True)

完成这些更改后,每次单击按钮将取消当前after周期并开始一个新的周期,从而防止一次运行多个周期,这应使LED保持同步。


查看完整回答
反对 回复 2021-03-30
  • 1 回答
  • 0 关注
  • 265 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信