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

Tkinter Entry组件设置readonly模式后变灰,如何仅禁止编辑?

如何让Tkinter Entry组件只读但保持正常外观(不变灰)?

我在开发项目时,想把Tkinter的Entry组件设置为只读模式,禁止用户修改内容,但设置state='readonly'后输入框会变灰(如图左上角输入框所示),不符合需求。请问有什么解决办法?

# Render canvas to contain tabular results from character table with scrollbars for GUI functionality

self.character_records_canvas = tkinter.Canvas(self.options_main_frame, width = 1150, height = 800)

# Define properties of scrollbars to render on frame 

self.scrollbar_vertical = tkinter.Scrollbar(self.options_main_frame, orient = tkinter.VERTICAL, command = self.character_records_canvas.yview)
self.scrollbar_horizontal = tkinter.Scrollbar(self.options_main_frame, orient = tkinter.HORIZONTAL, command = self.character_records_canvas.xview)

# Pack widget objects into main frame

self.scrollbar_horizontal.pack(side = tkinter.BOTTOM, fill = tkinter.X)
self.scrollbar_vertical.pack(side = tkinter.RIGHT, fill = tkinter.Y)
self.character_records_canvas.pack(side = tkinter.LEFT, fill = tkinter.BOTH, expand = 1)

# Configure canvas to communicate with scrollbars

self.character_records_canvas.configure(yscrollcommand=self.scrollbar_vertical.set)
self.character_records_canvas.configure(xscrollcommand=self.scrollbar_horizontal.set)

# Bind box around canvas to enable scrollbar functionality 

self.character_records_canvas.bind('<Configure>', lambda e : self.character_records_canvas.configure(scrollregion = self.character_records_canvas.bbox("all")))

# Render child frame in canvas to display tabular results

self.character_records_frame = tkinter.Frame(self.character_records_canvas)
self.character_records_frame.pack(side = tkinter.LEFT, fill = tkinter.BOTH, expand = 1)

# Configure the child frame to communicate with the canvas

self.character_records_canvas.create_window((0,0), window = self.character_records_frame, anchor = "nw")
self.character_records_canvas.configure(scrollregion = self.character_records_canvas.bbox("all"))

# Return list of results from character database table

query = "USE tictactoe_office_db;"
self.db_obj.execute_query(query)

query = """
SELECT * FROM `character`;
"""

character_results_list = self.db_obj.read_query(query)

# Render table column headers on frame

self.character_id_header = tkinter.Entry(self.character_records_frame, state = 'readonly')
self.first_name_header = tkinter.Entry(self.character_records_frame)
self.last_name_header = tkinter.Entry(self.character_records_frame)
self.branch_name_header = tkinter.Entry(self.character_records_frame)
self.game_wins_header = tkinter.Entry(self.character_records_frame)
self.game_losses_header = tkinter.Entry(self.character_records_frame)
self.match_wins_header = tkinter.Entry(self.character_records_frame)
self.match_ties_header = tkinter.Entry(self.character_records_frame)
self.match_losses_header = tkinter.Entry(self.character_records_frame)
self.match_total_header = tkinter.Entry(self.character_records_frame)
self.character_id_header.grid(row = 3, column = 0, sticky = "w")
self.first_name_header.grid(row = 3, column = 1, sticky = "w")
self.last_name_header.grid(row = 3, column = 2, sticky = "w")
self.branch_name_header.grid(row = 3, column = 3, sticky = "w")
self.game_wins_header.grid(row = 3, column = 4, sticky = "w")
self.game_losses_header.grid(row = 3, column = 5, sticky = "w")
self.match_wins_header.grid(row = 3, column = 6, sticky = "w")
self.match_ties_header.grid(row = 3, column = 7, sticky = "w")
self.match_losses_header.grid(row = 3, column = 8, sticky = "w")
self.match_total_header.grid(row = 3, column = 9, sticky = "w")  
self.character_id_header.insert(0, "character_id")
self.first_name_header.insert(0, "first_name")
self.last_name_header.insert(0, "last_name")
self.branch_name_header.insert(0, "branch_name")
self.game_wins_header.insert(0, "game_wins")
self.game_losses_header.insert(0, "game_losses")
self.match_wins_header.insert(0, "match_wins")
self.match_ties_header.insert(0, "match_ties")
self.match_losses_header.insert(0, "match_losses")
self.match_total_header.insert(0, "match_total")          

# Render tabular results on child frame

for i in range(0, len(character_results_list)):
    for j in range(0,len(character_results_list[0])):
        self.entry = tkinter.Entry(self.character_records_frame)
        self.entry.grid(row = i + 4, column = j, sticky = "w")
        self.entry.insert(tkinter.END, str(character_results_list[i][j]))

# Render column header border labels

for i in range(0, 10):
    self.character_records_menu_label_2 = tkinter.Entry(self.character_records_frame)
    self.character_records_menu_label_2.grid(row = 2, column = i, sticky = "n")
    self.character_records_menu_label_2.insert(0, "-----------------------------------")

# Render "back" buttons

self.options_back_button_1 = tkinter.Button(self.character_records_frame, text = "BACK", width = 10, command = self.destroy_character_records_canvas)
self.options_back_button_1.grid(row = 47, column = 9)
self.options_back_button_2 = tkinter.Button(self.character_records_frame, text = "BACK", width = 10, command = self.destroy_character_records_canvas)
self.options_back_button_2.grid(row = 47, column = 0)

输入框变灰效果


解决方法

方法1:绑定事件阻止输入操作

保持Entry的state='normal',但绑定相关事件阻止用户输入、粘贴等修改操作:

# 创建Entry时不设置readonly,绑定事件拦截操作
self.character_id_header = tkinter.Entry(self.character_records_frame)
# 阻止按键输入
self.character_id_header.bind("<Key>", lambda e: "break")
# 阻止右键粘贴(Windows/Linux)
self.character_id_header.bind("<Button-2>", lambda e: "break")
# 阻止Mac快捷键粘贴
self.character_id_header.bind("<Command-v>", lambda e: "break")
# 插入内容
self.character_id_header.insert(0, "character_id")

这种方式下Entry外观和正常状态完全一致,用户无法修改内容,但仍可选中复制。

方法2:用disabled状态并修正样式

如果使用state='disabled',可以手动设置前景色和背景色为正常Entry的样式,抵消变灰效果:

# 获取父容器的默认颜色(和正常Entry一致)
normal_fg = self.character_records_frame.cget("fg")
normal_bg = self.character_records_frame.cget("bg")

# 创建disabled状态的Entry并设置样式
self.character_id_header = tkinter.Entry(
    self.character_records_frame, 
    state='disabled',
    fg=normal_fg,
    bg=normal_bg
)
# 注意:修改内容时需要临时切换状态
self.character_id_header.config(state='normal')
self.character_id_header.insert(0, "character_id")
self.character_id_header.config(state='disabled')

方法3:自定义只读Entry类

如果多处需要使用,可封装一个复用的只读Entry组件:

class ReadOnlyEntry(tkinter.Entry):
    def __init__(self, master=None, **kwargs):
        super().__init__(master, **kwargs)
        # 绑定所有修改相关事件
        self.bind("<Key>", lambda e: "break")
        self.bind("<Button-2>", lambda e: "break")
        self.bind("<Command-v>", lambda e: "break")

# 使用时直接创建
self.character_id_header = ReadOnlyEntry(self.character_records_frame)
self.character_id_header.insert(0, "character_id")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 05:01:11