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

使用Tkinter开发进程联动程序时遇GUI卡顿问题求助

问题分析与解决方案

你的程序卡顿的核心原因是在tkinter主线程中执行了耗时的进程遍历操作。psutil.process_iter()会枚举系统所有进程,这个操作需要一定时间,而tkinter是单线程模型,主线程被阻塞时,UI更新(比如upd方法里的计数器刷新)就会停滞,导致界面卡顿。

修复方案:用子线程处理进程检查逻辑

把进程检测的任务放到独立线程中执行,让主线程专注处理UI交互和更新。子线程不能直接操作tkinter的UI元素,所以需要通过win.after()方法向主线程发送消息,由主线程处理弹窗或窗口关闭。

修改后的代码如下:

import tkinter as tk 
from tkinter import messagebox
import psutil
import os
import threading
import time


class myapp():
    def __init__(self):
        self.win = tk.Tk()
        self.win.title("test")
        self.win.geometry('200x100')
        self.win.config(bg='black')
        self.win.resizable(False,False)
        self.ctr = 0
        self.tk_var = tk.StringVar()
        self.tk_var.set("0")
        self.running = True  # 控制子线程运行的标志
        
        lab=tk.Label(self.win, textvariable=self.tk_var,
                     bg='black', fg='#FF0000')
        lab.place(x=90, y=45)
        
        btn = tk.Button(self.win,text='test',command='',
                        bd=0,bg='#7E1600',width=10,
                        activebackground='#6D0000')
        btn.pack(pady=20)
        
        self.upd()
        # 启动子线程处理进程检查
        threading.Thread(target=self.test, daemon=True).start()
        self.win.mainloop()

    def upd(self):
        if self.running:
            self.ctr += 1
            self.tk_var.set(str(self.ctr))
            self.win.after(50,self.upd)

    def test(self):
        while self.running:
            # 检查进程是否存在
            process_exists = "notepad.exe" in (i.name() for i in psutil.process_iter())
            if not process_exists:
                # 通知主线程显示弹窗
                self.win.after(0, self.show_error_and_exit)
                break
            time.sleep(0.5)  # 每隔0.5秒检查一次

    def show_error_and_exit(self):
        er = messagebox.showerror(title='error', message='notepad.exe has been stopped')
        if er == 'ok':
            self.running = False
            self.win.destroy()

os.popen('notepad')
myapp()

关键修改点:

  • 添加self.running标志,用于控制子线程和UI更新循环的启停
  • 将test方法放到子线程中执行,用time.sleep(0.5)替代after实现定时检查
  • 子线程中通过self.win.after(0, ...)触发主线程执行UI相关操作(弹窗、关闭窗口)
  • 设置子线程为daemon=True,确保主线程退出时子线程也会自动结束

这样修改后,进程检查的耗时操作不会阻塞主线程,UI就能保持流畅更新,同时也能实现进程联动的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 05:10:54