Копируемый прокручиваемый текст в tkinter

Я хотел создать прокручиваемый, копируемый текст в tkinter. Этот текст должен быть неизменным для пользователя, но я могу его изменить.

Хотя это кажется простым, есть несколько подходов к этому, но в каждом подходе есть неудовлетворительные моменты.*

  1. Используйте виджет state=disabledText.

Однако это также запрещает моей программе изменять его, что означает, что я должен временно включить виджет, что может привести к тому, что пользователь добавит один или два символа, если он спамит ключ в текстовом поле. (Да, это имеет значение, я хочу он должен быть абсолютно неизменным.)

  1. Используйте create_text для Canvas, который можно прокручивать.

Однако, насколько я знаю, я не могу скопировать такой текст.

  1. 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]

Как насчет возвращения "break" с таких мероприятий, как KeyPress?

TheLizzard 30.12.2022 14:34

подождите, вы можете сделать это?

00001H 31.12.2022 07:13
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
74
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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.

Сергей Кох 30.12.2022 08:13
Ответ принят как подходящий

Как насчет этого подхода?:

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", ...).

упс, не думал, что ты так умеешь. Я всегда думал, что вы можете только добавить собственный обработчик, но не блокировать обработку по умолчанию. Спасибо!

00001H 31.12.2022 07:17

Кроме того, я думаю, что замена return_break на (lambda x:'break') будет более понятной, но оба варианта работают.

00001H 31.12.2022 07:24

Обратите внимание, что в некоторых системах на основе X11 (например, Linux) некоторые оконные менеджеры имеют привязки по умолчанию, которые позволяют вставлять с помощью мыши. Если вы оставите виджет включенным, пользователь сможет вставлять данные, используя только мышь.

Bryan Oakley 31.12.2022 07:54

@BryanOakley Верно, но этот подход можно распространить и на такие события, как "<Mouse-3>". Но ваш ответ более правильный, учитывая, что OP не вставляет текстовое поле из других потоков, что нецелесообразно.

TheLizzard 31.12.2022 13:31

... Мне нужно временно включить виджет, что может привести к тому, что пользователь добавит один или два символа, если он спамит ключ в текстовом поле. (Да, это имеет значение, я хочу, чтобы он был абсолютно неизменным.)

Я не согласен с этим утверждением. Пользователь не сможет изменить текстовый виджет, если вы включите виджет, вставите или удалите текст, а затем отключите виджет в небольшом блоке кода. В этом блоке никакие события не обрабатываются, поэтому пользователь не может вводить данные в этот период времени. К тому времени, когда вы позволите tkinter снова начать обработку событий, виджет будет сброшен в отключенное состояние.

Правильное решение - установить состояние отключено и временно включить его, когда вашей программе необходимо вставить данные.

но обратные вызовы tkinter являются THREADED. Я не хочу попасть в яму условий гонки.

00001H 31.12.2022 07:14

@ 00001H: «но обратные вызовы tkinter ПОТОЧНЫЕ». - нет, они не. Tkinter является однопоточным. События помещаются в очередь, которая обрабатывается основным потоком.

Bryan Oakley 31.12.2022 07:43

Другие вопросы по теме

Похожие вопросы

Есть ли способ сделать условные определения словаря в python?
Как транспонировать список списков?
Превратите цветное изображение в изображение с искусственным цветом, также известное как простая (1D) LUT в Python
Python discord.py — команда косой черты не отображается на сервере
Не удалось установить conda, продолжайте сталкиваться с решением Среда решения: сбой при первоначальном замороженном решении. Повторная попытка с гибким решением
Получить элемент вывода за элементом при вводе списка
Как я могу фильтровать несколько фреймов данных с несколькими условиями (панды)?
Преобразование ячейки кода ноутбука Jupyter в блок кода
Как я могу упорядочить даты и показать только месяц + год по оси x в matplotlib?
Как мне написать бота, который отправляет своему владельцу прямое сообщение всякий раз, когда целевой пользователь меняет свой пользовательский статус?