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

如何用停止按钮终止另一个文件中的Tkinter循环?

问题:点击Stop按钮无法终止子线程中的循环

问题根源

  1. 线程创建错误:创建线程时直接调用了subroutine.routine(pressed),导致主线程在启动新线程前就执行该函数,死循环会直接卡住主线程,根本无法启动子线程。正确做法是将函数对象传给target,通过args传递参数。
  2. 值传递的局限性:pressed是整数(不可变类型),传递给子函数的是值的副本。主线程修改pressed的值后,子函数里的副本不会同步更新,因此永远触发不了break。

解决方案

方案1:用可变对象传递状态

利用Python可变对象(如列表)的引用特性,让子线程能读取到最新状态。

修改subroutine.py:

def routine(pressed_flag):
    while True:
        print("hello")
        if pressed_flag[0] == 1:
            break

修改主文件:

import tkinter as tk
import threading
import subroutine

# 用列表作为可变容器,存储状态
pressed = [0]

def Start_Scan():
    global pressed
    pressed[0] = 0
    # 正确传递函数对象和参数,args为元组格式
    t = threading.Thread(target=subroutine.routine, args=(pressed,))
    t.start()

def Stop():
    global pressed
    pressed[0] = 1

# 主窗口逻辑
master = tk.Tk()
app = tk.Frame(master)
app.grid()

start = tk.Button(app, text="Start Scan", command=Start_Scan)
stop = tk.Button(app, text="Stop", command=Stop)

start.grid()
stop.grid()

app.mainloop()

方案2:使用threading.Event(推荐)

threading.Event是Python专门用于线程通信的同步原语,比全局变量更安全可靠。

修改subroutine.py:

def routine(stop_event):
    while not stop_event.is_set():
        print("hello")

修改主文件:

import tkinter as tk
import threading
import subroutine

def Start_Scan():
    global stop_event
    # 每次启动扫描时创建新的Event对象
    stop_event = threading.Event()
    t = threading.Thread(target=subroutine.routine, args=(stop_event,))
    t.start()

def Stop():
    global stop_event
    # 设置事件,触发子线程终止循环
    stop_event.set()

# 主窗口逻辑
master = tk.Tk()
app = tk.Frame(master)
app.grid()

start = tk.Button(app, text="Start Scan", command=Start_Scan)
stop = tk.Button(app, text="Stop", command=Stop)

start.grid()
stop.grid()

app.mainloop()

说明

  • 方案1通过可变对象实现状态共享,适合简单场景;
  • 方案2用专门的线程同步工具,避免了竞态条件,是更专业的线程通信方式。

内容的提问来源于stack exchange,提问作者Juan Ignacio Ochotorena

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 10:17:23