[英]Readonly tkinter text widget
我想使用tkinter text widget
作為readonly
小部件。 它應該作為transcript
區域。 我的想法是將此腳本保存在一個file
,每當用戶寫入任何內容時,只需刪除該小部件的所有內容,然后重新重寫即可。
代碼如下所示:
transcript_entry = SimpleEditor() # SimpleEditor is inherited from ScrolledText
transcript_entry.text.delete("1.0", END)
# this is just a test string, it should be the contents of the transcript file
transcript_entry.text.insert("1.0", "This is test transcript")
transcript_entry.text.bind("<KeyPress>", transcript_entry.readonly)
readonly
函數看起來像:
def readonly(self, event):
self.text.delete("1.0", END)
# this is just a test string, it should be the contents of the transcript file
self.text.insert("1.0", "This is test transcript")
這里的錯誤是用戶輸入的最后一個字符被添加到記錄中。 我懷疑原因是調用了readonly函數, then
將用戶輸入寫入窗口小部件。 如何反轉此順序並after
將用戶輸入寫入窗口小部件after
調用readonly函數?
任何提示?
插入最后一個字符的原因是因為默認綁定(導致插入)發生在放在窗口小部件上的自定義綁定之后 。 因此,首先觸發綁定, 然后默認綁定插入字符。 這里還有其他問題和答案,可以更深入地討論這個問題。 例如,請參閱https://stackoverflow.com/a/11542200/
但是,有一種更好的方法可以完成您想要做的事情。 如果要創建只讀文本窗口小部件,可以將state
屬性設置為"disabled"
。 這將阻止所有插入和刪除(並且意味着您需要在以編程方式輸入數據時還原狀態)。
在某些平台上,您似乎無法突出顯示和復制文本,但這只是因為默認情況下窗口小部件不會專注於鼠標單擊。 通過添加綁定來設置焦點,用戶可以突出顯示和復制文本,但無法剪切或插入。
這是使用python 2.x的一個例子; 對於3.x,您只需更改導入:
import Tkinter as tk
from ScrolledText import ScrolledText
class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
t = ScrolledText(self, wrap="word")
t.insert("end", "Hello\nworld")
t.configure(state="disabled")
t.pack(side="top", fill="both", expand=True)
# make sure the widget gets focus when clicked
# on, to enable highlighting and copying to the
# clipboard.
t.bind("<1>", lambda event: t.focus_set())
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
請不要刪除並重新插入文本:
我發現創建只讀文本的最佳方法是禁用導致文本更改的所有綁定。
我的解決方案是創建一個只包含“只讀命令”的新Widget綁定映射。 然后,只需重新配置您的小部件以使用新的RO綁定映射而不是默認的:
from Tkinter import *
# This is the list of all default command in the "Text" tag that modify the text
commandsToRemove = (
"<Control-Key-h>",
"<Meta-Key-Delete>",
"<Meta-Key-BackSpace>",
"<Meta-Key-d>",
"<Meta-Key-b>",
"<<Redo>>",
"<<Undo>>",
"<Control-Key-t>",
"<Control-Key-o>",
"<Control-Key-k>",
"<Control-Key-d>",
"<Key>",
"<Key-Insert>",
"<<PasteSelection>>",
"<<Clear>>",
"<<Paste>>",
"<<Cut>>",
"<Key-BackSpace>",
"<Key-Delete>",
"<Key-Return>",
"<Control-Key-i>",
"<Key-Tab>",
"<Shift-Key-Tab>"
)
class ROText(Text):
tagInit = False
def init_tag(self):
"""
Just go through all binding for the Text widget.
If the command is allowed, recopy it in the ROText binding table.
"""
for key in self.bind_class("Text"):
if key not in commandsToRemove:
command = self.bind_class("Text", key)
self.bind_class("ROText", key, command)
ROText.tagInit = True
def __init__(self, *args, **kwords):
Text.__init__(self, *args, **kwords)
if not ROText.tagInit:
self.init_tag()
# Create a new binding table list, replace the default Text binding table by the ROText one
bindTags = tuple(tag if tag!="Text" else "ROText" for tag in self.bindtags())
self.bindtags(bindTags)
text = ROText()
text.insert("1.0", """A long text with several
lines
in it""")
text.pack()
text.mainloop()
請注意,只是更改了綁定。 所有Text命令(如insert,delete,...)仍然可用。
我最近使用了一種不同的,稍微簡單的解決方案。 可以添加一個函數來刪除所有輸入字符,而不是更改所有綁定:
def read_only(self, event):
if event.char is not '': # delete only if the key pressed
# corresponds to an actual character
self.text.delete('insert-1c')
並將其綁定到任何事件:
root.bind('<Key>', self.read_only)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.