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

扫描三个条码后刷新Tkinter GUI并对比字符串的实现问题

Tkinter条码扫描校验工具开发问题

我刚接触Python,对Tkinter GUI开发也较为陌生。目前正在做一个工作项目,需求是实现三个条码的扫描,提取条码最后9位进行对比,完全匹配则显示"pass",否则显示"fail"。我已经用基础命令行实现了全部逻辑,现在尝试将其改为GUI界面,遇到了实现障碍。

当前遇到的问题是不知道如何正确更新/刷新界面。现有逻辑仅在代码运行前就给ENTRY文本框输入字符串时才能正常判断:字符串不一致时返回fail,一致或为空时返回pass。

我需要实现的效果是:扫描三个序列号后底部框架自动更新pass或fail结果,之后可以继续扫描下一组序列号得到新的校验结果。我的原始代码如下:

from tkinter import *


# 自动跳转到下一个输入框的函数
def go_to_next_entry(event, entry_list, this_index):
    next_index = (this_index + 1) % len(entry_list)
    entry_list[next_index].focus_set()


# 校验三个序列号是否一致,根据结果显示pass/fail的函数
def get_results():
    # 从输入框获取输入内容
    scan_one = scan_one_entry.get()
    scan_two = scan_two_entry.get()
    scan_three = scan_three_entry.get()

    # 提取输入字符串最后9位
    parsed_scan_one = scan_one[-9:]
    parsed_scan_two = scan_two[-9:]
    parsed_scan_three = scan_three[-9:]

    # 三个序列号一致则显示pass,否则显示fail
    if parsed_scan_one == parsed_scan_two and parsed_scan_two == parsed_scan_three and parsed_scan_three == parsed_scan_one:
        # 清空输入框内容
        scan_one_entry.delete(0, END)
        scan_two_entry.delete(0, END)
        scan_three_entry.delete(0, END)

        # 显示pass底部框架
        pass_bottom_frame.grid(row=1, sticky="ns, ew")

        # 创建pass提示标签
        pass_label = Label(pass_bottom_frame,
                           text='PASSED SCAN CHECK!',
                           font=('Helvetica', 100),
                           justify="center")
        pass_label.config(bg="#63d464", fg="#000000")
        pass_label.place(relx=.5, rely=.5, anchor="center")
    else:
        # 清空输入框内容
        scan_one_entry.delete(0, END)
        scan_two_entry.delete(0, END)
        scan_three_entry.delete(0, END)

        # 显示fail底部框架
        fail_bottom_frame.grid(row=1, sticky="ns, ew")

        # 创建fail提示标签
        fail_label = Label(fail_bottom_frame,
                           text='FAILED SCAN CHECK!',
                           font=('Helvetica', 100),
                           justify="center")
        fail_label.config(bg="#f51023", fg="#000000")
        fail_label.place(relx=.5, rely=.5, anchor="center")

# 创建主窗口
main_window = Tk()
main_window.title('Serial Number Barcode Scan Check')
main_window.state("zoomed")

# 创建主框架
top_frame = Frame(main_window, width=1800, height=500)
pass_bottom_frame = Frame(main_window, bg="#63d464",  width=1800, height=500)
fail_bottom_frame = Frame(main_window, bg="#f51023",  width=1800, height=500)

# 布局配置
main_window.grid_rowconfigure(1, weight=1)
main_window.grid_columnconfigure(0, weight=1)

# 放置顶部框架
top_frame.grid(row=0, sticky="ns, ew")

# 创建顶部框架控件
scan_one_label = Label(top_frame,
                       text='ENTER SCAN ONE: ',
                       font=('Helvetica', 40))
scan_two_label = Label(top_frame,
                       text='ENTER SCAN TWO: ',
                       font=('Helvetica', 40))
scan_three_label = Label(top_frame,
                         text='ENTER SCAN THREE: ',
                         font=('Helvetica', 40))
scan_one_entry = Entry(top_frame, font="Helvetica 20", justify="center", border=5)
scan_two_entry = Entry(top_frame, font="Helvetica 20", justify="center", border=5)
scan_three_entry = Entry(top_frame, font="Helvetica 20", justify="center", border=5)

# 放置顶部框架控件
scan_one_label.grid(row=0, column=0, sticky='w')
scan_two_label.grid(row=1, column=0, sticky='w')
scan_three_label.grid(row=2, column=0, sticky='w')
scan_one_entry.grid(row=0, column=1, ipadx=100, ipady=8)
scan_two_entry.grid(row=1, column=1, ipadx=100, ipady=8)
scan_three_entry.grid(row=2, column=1, ipadx=100, ipady=8)

# 绑定回车事件实现自动跳转
entries = [child for child in top_frame.winfo_children() if isinstance(child, Entry)]
for index, entry in enumerate(entries):
    entry.bind('<Return>', lambda e, index=index: go_to_next_entry(e, entries, index))

# 调用校验函数
get_results()

# 主事件循环
main_window.mainloop()

修复方案

核心问题说明

当前代码存在几个关键问题导致无法实现预期效果:

  • 仅在程序启动时调用了一次get_results(),后续扫描输入完成后没有触发校验逻辑
  • 每次显示pass/fail提示时重复创建Label控件,多次校验会导致控件叠加冗余
  • 没有对空输入做校验,三个空串的最后9位都为空,会被误判为pass
  • 显示新的结果框架前没有隐藏之前的框架,会导致两个状态的框架叠加显示

修复后完整代码

from tkinter import *


def go_to_next_entry(event, entry_list, this_index):
    next_index = (this_index + 1) % len(entry_list)
    entry_list[next_index].focus_set()
    # 第三次输入完成按回车后,跳回第一个输入框前触发校验
    if next_index == 0:
        get_results()


def get_results():
    scan_one = scan_one_entry.get().strip()
    scan_two = scan_two_entry.get().strip()
    scan_three = scan_three_entry.get().strip()

    # 非空校验,三个输入都不为空才进行判断
    if not all([scan_one, scan_two, scan_three]):
        return

    parsed_scan_one = scan_one[-9:]
    parsed_scan_two = scan_two[-9:]
    parsed_scan_three = scan_three[-9:]

    # 先隐藏两个结果框架
    pass_bottom_frame.grid_remove()
    fail_bottom_frame.grid_remove()

    if parsed_scan_one == parsed_scan_two == parsed_scan_three:
        pass_bottom_frame.grid(row=1, sticky="ns, ew")
    else:
        fail_bottom_frame.grid(row=1, sticky="ns, ew")

    # 清空输入框,定位回第一个输入框准备下一次扫描
    scan_one_entry.delete(0, END)
    scan_two_entry.delete(0, END)
    scan_three_entry.delete(0, END)
    scan_one_entry.focus_set()


main_window = Tk()
main_window.title('条码扫描校验工具')
main_window.state("zoomed")

top_frame = Frame(main_window, width=1800, height=500)
pass_bottom_frame = Frame(main_window, bg="#63d464", width=1800, height=500)
fail_bottom_frame = Frame(main_window, bg="#f51023", width=1800, height=500)

main_window.grid_rowconfigure(1, weight=1)
main_window.grid_columnconfigure(0, weight=1)

top_frame.grid(row=0, sticky="ns, ew")

# 提前创建好结果标签,不用每次重复生成
pass_label = Label(pass_bottom_frame,
                   text='扫描校验通过!',
                   font=('Helvetica', 100),
                   justify="center",
                   bg="#63d464",
                   fg="#000000")
pass_label.place(relx=.5, rely=.5, anchor="center")

fail_label = Label(fail_bottom_frame,
                   text='扫描校验不通过!',
                   font=('Helvetica', 100),
                   justify="center",
                   bg="#f51023",
                   fg="#000000")
fail_label.place(relx=.5, rely=.5, anchor="center")

# 顶部输入区域控件
scan_one_label = Label(top_frame,
                       text='请扫描第一个条码:',
                       font=('Helvetica', 40))
scan_two_label = Label(top_frame,
                       text='请扫描第二个条码:',
                       font=('Helvetica', 40))
scan_three_label = Label(top_frame,
                         text='请扫描第三个条码:',
                         font=('Helvetica', 40))
scan_one_entry = Entry(top_frame, font="Helvetica 20", justify="center", border=5)
scan_two_entry = Entry(top_frame, font="Helvetica 20", justify="center", border=5)
scan_three_entry = Entry(top_frame, font="Helvetica 20", justify="center", border=5)

scan_one_label.grid(row=0, column=0, sticky='w', padx=20, pady=20)
scan_two_label.grid(row=1, column=0, sticky='w', padx=20, pady=20)
scan_three_label.grid(row=2, column=0, sticky='w', padx=20, pady=20)
scan_one_entry.grid(row=0, column=1, ipadx=100, ipady=8, padx=20, pady=20)
scan_two_entry.grid(row=1, column=1, ipadx=100, ipady=8, padx=20, pady=20)
scan_three_entry.grid(row=2, column=1, ipadx=100, ipady=8, padx=20, pady=20)

entries = [scan_one_entry, scan_two_entry, scan_three_entry]
for index, entry in enumerate(entries):
    entry.bind('<Return>', lambda e, index=index: go_to_next_entry(e, entries, index))

# 初始定位到第一个输入框
scan_one_entry.focus_set()

main_window.mainloop()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 03:15:03