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

求助:Tkinter窗口可通过退出按钮关闭,串口指令触发关闭失败

问题:Tkinter窗口无法通过串口指令关闭,点击按钮正常

尝试通过两种方式关闭Tkinter窗口:

  • 点击界面的Quit退出按钮(功能正常)
  • 通过Arduino连接的遥控器发送串口指令(按下0键无法关闭窗口,报错can't invoke "destroy" command)

有问题的测试代码:

# the 1st code start
from tkinter import *
import serial
import time

window = Tk()
window.geometry("300x300")

def close_window():
    window.destroy()

button = Button(text="Quit",font=("Arial",10), command=close_window)
button.pack()

ser = serial.Serial("COM5", 115200)

window.mainloop()

while True:
    var2 = ser.readline()

    # press the remote control 0, then break
    if var2 == b'0\r\n': 
        close_window()
        print('Exit the code')
        break

    # press the remote control 1, then continue (just for testing purposes)
    elif var2 == b'1\r\n':
        print('Continue the code')
        pass 

    time.sleep(0.01)

单独测试串口指令终止脚本的功能正常,对应代码:

# the 2nd code start
import serial
import time

ser = serial.Serial("COM5", 115200)

while True:
    var2 = ser.readline()

    # press the remote control 0, then break
    if var2 == b'0\r\n': 
        print('Exit the code')
        break

    # press the remote control 1, then continue (just for testing purposes)
    elif var2 == b'1\r\n':
        print('Continue the code')
        pass

    time.sleep(0.01)

解决方案

核心问题:

  1. window.mainloop()会阻塞后续代码执行,直到窗口关闭,此时window对象已被销毁,再调用close_window()必然报错。
  2. Tkinter是单线程框架,主循环外的while循环会阻塞UI响应,同时无法和主循环交互。

修改后的代码:

from tkinter import *
import serial

window = Tk()
window.geometry("300x300")

# 初始化串口
ser = serial.Serial("COM5", 115200)

def close_window():
    ser.close()  # 释放串口资源
    window.destroy()

def check_serial():
    # 检查串口是否有数据等待读取
    if ser.in_waiting > 0:
        # 读取数据并去除首尾空白(包括换行、回车)
        var2 = ser.readline().strip()
        if var2 == b'0':
            close_window()
            print('Exit the code')
        elif var2 == b'1':
            print('Continue the code')
    # 每隔10毫秒再次调用自身,实现轮询
    window.after(10, check_serial)

button = Button(text="Quit", font=("Arial",10), command=close_window)
button.pack()

# 启动串口轮询
check_serial()

window.mainloop()

修改说明

  • 把串口初始化移到主循环前,确保程序启动时就建立串口连接。
  • 使用Tkinter的after()方法替代while循环,在主循环中异步轮询串口,既不阻塞UI,又能实时响应串口指令。
  • 读取串口数据时用strip()处理,避免因换行符格式(\r\n/\n)导致的匹配失败。
  • 关闭窗口前先关闭串口,避免资源泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 05:43:33