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

Tkinter程序运行一段时间后无法加载新窗口问题求助

Tkinter弹窗空白问题修复方案

问题背景

开发的Tkinter GUI程序可将界面录入条目记录到Access数据库,初始运行正常,但使用Stock或Pick按钮提交操作一段时间后,确认提示等新窗口无法正常加载,仅显示空白弹窗,需重启程序才能恢复,问题涉及safetyCheckStock()和safetyCheckPick()函数。

问题根源

  1. 数据库连接泄漏:所有数据库操作函数创建连接后未关闭,长时间运行导致连接资源耗尽,阻塞UI线程。
  2. 全局窗口变量冲突:所有弹窗共用同一个全局newWindow,弹窗创建/销毁时序异常时,会导致Tkinter无法正确渲染新窗口。
  3. SQL注入风险:直接拼接SQL语句,不仅存在安全隐患,还可能因特殊字符导致查询失败,间接引发UI异常。

修复步骤

1. 修复数据库连接泄漏

使用with语句自动管理连接和游标,确保每次操作后关闭连接,同时改用参数化查询避免SQL注入:

# 修改findOldQty函数
def findOldQty():
    tablename = 'tblPCB_Inventory'
    job = retrieveJob()
    pcb_type = retrievePcbType()
    # with语句自动关闭连接和游标
    with get_dbconn(r'Y:\\Inventory\\INVENTORY TABLE.mdb') as dbconn:
        with dbconn.cursor() as cursor:
            sql = f"select * from [{tablename}] where job = ? and pcb_type= ?;"
            cursor.execute(sql, (job, pcb_type))
            rows = cursor.fetchall()
            return int(rows[0].Qty) if rows else None

# 修改stockPCB函数的数据库操作部分
def stockPCB():
    if retrieveJob() == "" or retrieveLoc() == "" or str(retrievePcbType()) == "0" or retrieveQty() == "":
        checkFields()
        return
    
    oldQty = findOldQty()
    tablename = 'tblPCB_Inventory'
    job = retrieveJob()
    pcb_type = retrievePcbType()
    qty = retrieveQty()
    loc = retrieveLoc()
    
    with get_dbconn(r'Y:\\Location\\INVENTORY TABLE.mdb') as dbconn:
        with dbconn.cursor() as cursor:
            if oldQty is None:
                sql = f"insert into [{tablename}](job, pcb_type, qty, location) values (?, ?, ?, ?);"
                cursor.execute(sql, (job, pcb_type, qty, loc))
                stockComplete(qty)
            else:
                newQty = oldQty + int(qty)
                sql = f"update [{tablename}] set qty = ? where job = ? and pcb_type = ?;"
                cursor.execute(sql, (newQty, job, pcb_type))
                stockComplete(newQty)
            dbconn.commit()

# 修改pickPCB函数的数据库操作部分
def pickPCB():
    if retrieveJob() == "" or retrieveLoc() == "" or retrievePcbType() == "" or retrieveQty() == "":
        checkFields()
        return
    
    oldQty = findOldQty()
    if oldQty is None:
        wrongJob()
        return
    
    newQty = oldQty - int(retrieveQty())
    if newQty < 0:
        lowQuantity()
        return
    
    tablename = 'tblPCB_Inventory'
    job = retrieveJob()
    pcb_type = retrievePcbType()
    
    with get_dbconn(r'Y:\\Inventory\\INVENTORY TABLE.mdb') as dbconn:
        with dbconn.cursor() as cursor:
            sql = f"update [{tablename}] set qty = ? where job = ? and pcb_type = ?;"
            cursor.execute(sql, (newQty, job, pcb_type))
            dbconn.commit()
            pickComplete()

2. 避免全局窗口变量冲突

取消全局newWindow定义,改为每个弹窗函数内部创建局部变量,通过lambda传递窗口对象到关闭函数:

# 修改closeNewWindow函数,接收窗口参数
def closeNewWindow(window, event=None):
    window.destroy()
    app.focus_set()
    varJob.focus_set()

# 示例:修改lowQuantity函数
def lowQuantity():
    newWindow = Toplevel(app)
    newWindow.title("Low Quantity")
    newWindow.geometry("400x200")
    newWindow.focus_set()
    icon = PhotoImage(file='logo.png')
    newWindow.iconphoto(False, icon)
    oldQty = findOldQty()
    Label(newWindow, text = f"Inventory has only {oldQty},\n pick {oldQty} or less.",font=("Arial bold", 24) ,fg="red").pack()
    newWindow.bind("<Return>", lambda e: closeNewWindow(newWindow))

# 其余弹窗函数(wrongJob、pickComplete、checkFields、stockComplete、safetyCheckPick、safetyCheckStock)均按此方式修改,移除全局newWindow

3. 优化UI线程响应

将数据库操作放入子线程,避免阻塞Tkinter事件循环(针对耗时操作):

import threading

# 修改safetyDecisionStock函数
def safetyDecisionStock(decision):
    newWindow.destroy()
    if decision:
        threading.Thread(target=stockPCB, daemon=True).start()

# 修改safetyDecisionPick函数
def safetyDecisionPick(decision):
    newWindow.destroy()
    if decision:
        threading.Thread(target=pickPCB, daemon=True).start()

额外优化建议

  • 用Entry组件替代Text组件处理单行输入,简化取值逻辑。
  • 增加输入类型校验(如Quantity必须为整数),避免数据库操作报错。
  • 将数据库路径、表名等配置抽离为常量,便于后续维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 10:39:53