Я хотел создать прокручиваемый, копируемый текст в tkinter. Этот текст должен быть неизменным для пользователя, но я могу его изменить.
Хотя это кажется простым, есть несколько подходов к этому, но в каждом подходе есть неудовлетворительные моменты.*
state=disabledText.Однако это также запрещает моей программе изменять его, что означает, что я должен временно включить виджет, что может привести к тому, что пользователь добавит один или два символа, если он спамит ключ в текстовом поле. (Да, это имеет значение, я хочу он должен быть абсолютно неизменным.)
Canvas, который можно прокручивать.Однако, насколько я знаю, я не могу скопировать такой текст.
pack Метки в Canvas, который можно прокручивать.Однако, насколько я знаю, они не прокручиваются вместе с холстом.
Одна вещь, которая могла бы работать, это Canvas.create_window, но я даже не могу найти документ об этом, а текст help не говорит ничего полезного.
help> tkinter.Canvas.create_window
Help on function create_window in tkinter.Canvas:
tkinter.Canvas.create_window = create_window(self, *args, **kw)
Create window with coordinates x1,y1,x2,y2.
help>
[sic]
подождите, вы можете сделать это?






import tkinter as tk
from tkinter import scrolledtext
# Create the root window
root = tk.Tk()
# Create a ScrolledText widget with the specified text
text = scrolledtext.ScrolledText(root, wrap='word')
text.insert('1.0', """This is some immutable text that can be scrolled and copied
...
.
.
.
.
.
.
.
.
..
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
This is some immutable text that can be scrolled and copied""")
# Configure the widget to be non-editable
text.config(state='disabled')
# Pack the widget and start the event loop
text.pack()
root.mainloop()
Вы не читали вопрос? Тогда смотрите пункт 1.
Как насчет этого подхода?:
from tkinter.scrolledtext import ScrolledText
import tkinter as tk
def return_break(event:tk.Event) -> str:
return "break"
root = tk.Tk()
text = ScrolledText(root)
text.pack()
text.bind("<KeyPress>", return_break)
text.insert("end", "Hello"+"\n"*40+"World.")
root.mainloop()
Вы возвращаетесь "break" из событий, которые вы не хотите tkinter обрабатывать как "<KeyPress>". Чтобы этот подход работал, при вставке нового текста не используйте .insert("insert", ...), так как пользователь может изменить это, вместо этого пользователь .insert("end", ...).
упс, не думал, что ты так умеешь. Я всегда думал, что вы можете только добавить собственный обработчик, но не блокировать обработку по умолчанию. Спасибо!
Кроме того, я думаю, что замена return_break на (lambda x:'break') будет более понятной, но оба варианта работают.
Обратите внимание, что в некоторых системах на основе X11 (например, Linux) некоторые оконные менеджеры имеют привязки по умолчанию, которые позволяют вставлять с помощью мыши. Если вы оставите виджет включенным, пользователь сможет вставлять данные, используя только мышь.
@BryanOakley Верно, но этот подход можно распространить и на такие события, как "<Mouse-3>". Но ваш ответ более правильный, учитывая, что OP не вставляет текстовое поле из других потоков, что нецелесообразно.
... Мне нужно временно включить виджет, что может привести к тому, что пользователь добавит один или два символа, если он спамит ключ в текстовом поле. (Да, это имеет значение, я хочу, чтобы он был абсолютно неизменным.)
Я не согласен с этим утверждением. Пользователь не сможет изменить текстовый виджет, если вы включите виджет, вставите или удалите текст, а затем отключите виджет в небольшом блоке кода. В этом блоке никакие события не обрабатываются, поэтому пользователь не может вводить данные в этот период времени. К тому времени, когда вы позволите tkinter снова начать обработку событий, виджет будет сброшен в отключенное состояние.
Правильное решение - установить состояние отключено и временно включить его, когда вашей программе необходимо вставить данные.
но обратные вызовы tkinter являются THREADED. Я не хочу попасть в яму условий гонки.
@ 00001H: «но обратные вызовы tkinter ПОТОЧНЫЕ». - нет, они не. Tkinter является однопоточным. События помещаются в очередь, которая обрабатывается основным потоком.
Как насчет возвращения
"break"с таких мероприятий, какKeyPress?