You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用tkinter.after()多次调用实现PLC脚本的时序执行逻辑?

Tkinter 时序控制问题解答

先给你明确两个核心结论:

  • 所有tkinter.after()的计时都是从你调用它的那一刻起独立算时间,不是等前一个after任务跑完才开始计时。
  • 像cycleStartWidget.grid()这种普通同步代码,会立刻执行,根本不会等after()里的延迟任务。

你给的代码里的问题

看你写的这段代码:

logStartWidget.grid()
widget.after(3000, lambda: plc.write((onTag,1)))
cycleStartWidget.grid() # 这行在logStartWidget.grid()之后马上就跑,不会等那3秒
cycleRunningWidget.grid()

# 这个after的计时和前一个同时开始,不是等plc.write完再算时间
widget.after(3000+cycle_runtime*1000, lambda: plc.write((onTag, 0)))

这里的问题很明显:

  1. 循环开始的控件会直接显示,不符合你终端脚本里“等3秒再提示循环启动”的逻辑
  2. 第二个after()的计时和第一个同时启动,不是等PLC写入启动信号后再等cycle_runtime,时序完全不对

正确的实现方式

要完全复刻终端脚本的流程,得把后续步骤嵌套到前一个after()的回调里,形成链式执行:

def start_logging():
    logStartWidget.grid()
    # 启动日志子进程
    logger = subprocess.Popen(*start logging args*)
    # 3秒后启动循环流程
    widget.after(3000, start_cycle, logger)

def start_cycle(logger):
    plc.write((onTag, 1))
    cycleStartWidget.grid()
    cycleRunningWidget.grid()
    # 等cycle_runtime秒后结束循环
    widget.after(int(cycle_runtime*1000), finish_cycle, logger)

def finish_cycle(logger):
    plc.write((onTag, 0))
    cycleRunningWidget.grid_remove()
    print("Cycle finished")
    logger.stop()

# 触发整个流程
start_logging()

这个逻辑和你终端脚本完全一致:

  1. 先显示日志启动控件,启动日志进程
  2. 等3秒,给PLC发启动信号,显示循环开始/运行的控件
  3. 等cycle_runtime秒,给PLC发停止信号,结束日志

额外提醒

  • 要是硬要用连续的after(),你得精确算每个任务的总延迟(比如第一个3000,第二个3000+cycle_runtime*1000),但这种方式很脆——如果PLC写入耗时,整个时序就乱了。嵌套调用的方式更靠谱,因为它是在前一个任务做完之后才开始算下一个的时间。
  • 如果你的PLC操作耗时比较久,最好放到子线程里跑,别卡住GUI。

内容的提问来源于stack exchange,提问作者narab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 16:20:17