扫描三个条码后刷新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
相关产品推荐
相关产品推荐

