如何让tkinter Entry组件设为只读且保留原有内容?
Tkinter Entry只读状态下保留内容的解决方案
问题说明
使用Python的tkinter开发JSON编辑器时,通过以下代码创建Entry输入框:
globals()[f"dv_{key}_{subkey}"] = tk.Entry(self.root, width=250)
添加state='disabled'参数实现只读后,输入框虽无法编辑,但原有内容消失。需要实现只读状态的同时正常显示设置只读前的内容。
解决方案
Tkinter的Entry组件在state='disabled'状态下无法插入或修改内容,因此正确的操作顺序是:
- 先创建**默认正常状态(
state='normal')**的Entry组件 - 插入需要显示的内容
- 最后将组件设置为
state='disabled'
如果需要允许用户选中复制内容但不能编辑,也可以保留state='normal',同时绑定<Key>事件阻止输入:
def disable_input(event): return "break" entry.bind("<Key>", disable_input)
这种方式下用户仍可选中复制内容,体验更友好。
另外需要注意:若后续要读取或修改Entry内容,必须先将组件恢复为state='normal',操作完成后再设回disabled,否则无法获取或修改内容。
修改后的完整JSON编辑器代码
import json import tkinter as tk class JsonEditor: def __init__(self, root, filename): self.root = root self.root.title("JSON Editor") self.json_data = {} self.textboxes = [] self.filename = filename self.read_file() self.create_widgets() def create_widgets(self): # 创建菜单栏 menubar = tk.Menu(self.root) filemenu = tk.Menu(menubar, tearoff=0) filemenu.add_command(label="保存", command=self.save_file) menubar.add_cascade(label="文件", menu=filemenu) self.root.config(menu=menubar) # 为JSON键值对创建输入框 row = 0 for key, value in self.json_data.items(): if isinstance(value, dict): label = tk.Label(self.root, text=key) label.grid(row=row, column=0) row += 1 for subkey, subvalue in value.items(): sublabel = tk.Label(self.root, text=subkey) sublabel.grid(row=row, column=1) # 先创建正常状态的Entry subtextbox = tk.Entry(self.root, width=50) # 插入内容 subtextbox.insert(0, subvalue) # 设置为只读状态 subtextbox.config(state='disabled') subtextbox.grid(row=row, column=2) self.textboxes.append((key, subkey, subtextbox)) row += 1 else: label = tk.Label(self.root, text=key) label.grid(row=row, column=0) textbox = tk.Entry(self.root, width=50) textbox.insert(0, value) textbox.config(state='disabled') textbox.grid(row=row, column=1) self.textboxes.append((key, textbox)) row += 1 # 创建提交按钮 submit_button = tk.Button(self.root, text="提交", command=self.save_file) submit_button.grid(row=row, column=1) def read_file(self): with open(self.filename, "r") as f: self.json_data = json.load(f) def save_file(self): # 保存前恢复正常状态,否则无法获取内容 for item in self.textboxes: if len(item) == 2: key, textbox = item textbox.config(state='normal') self.json_data[key] = textbox.get() textbox.config(state='disabled') elif len(item) == 3: key, subkey, subtextbox = item subtextbox.config(state='normal') self.json_data[key][subkey] = subtextbox.get() subtextbox.config(state='disabled') with open(self.filename, "w") as f: json.dump(self.json_data, f, indent=4) root = tk.Tk() # 设置窗口大小 root.geometry("800x600") # 设置JSON文件路径 filename = "C:/orderprepare.json" # 创建编辑器GUI editor = JsonEditor(root, filename) # 启动GUI主循环 root.mainloop()
示例JSON文件
{ "ShipTo": { "CustomerName1": "test test", "CustomerName2": "test test", "Phone": "000-000-0000dfswerwer", "Address1": "test test", "Address2": "dfewrwer", "City": "Tazewellddsewrer", "StateOrProvince": "TNdsfsewr", "PostalCode": "82823", "Country": "USA" }, "BillTo": { "CustomerName1": "test2 test2", "CustomerName2": "test2 test2", "Address1": "test test", "Address2": "dfewrwer", "City": "anywhere", "StateOrProvince": "TNdsfsewr", "PostalCode": "84747", "Country": "USA" }, "ItemList": [ { "ItemNumber": "itemxxxx111", "BuyerPartNumber": "partxxx1111", "Quantity": "7", "UnitPrice": "809" } ] }
内容的提问来源于stack exchange,提问作者Alex Co
相关产品推荐
相关产品推荐

