Текстовый виджет только для чтения в python3-tkinter; кроссплатформенный - PullRequest
6 голосов
/ 16 октября 2011

Как подавить возможность конечного пользователя редактировать / добавлять / удалять текст в текстовом виджете? (Python v3.2 .. и ткинтер)

Смысл в том, чтобы подавлять только возможность изменять / добавлять / удалять текст , но не кастрировать другие функции. Возможно, текстовое поле NoEdit будет более подходящим.

Я пробовал .text ['state'] = 'отключен' , и он работает почти ОК в Windows (он по-прежнему позволяет пользователю выбирать / копировать текст, выделяет выделение , кнопки «вверх / вниз» и «вверх / вниз» работают. Кажется, единственное, что сломано - курсор, сделанный невидимым.)

Но на MacIntosh все сломано. Без выделения, без выбора / копирования, ... UGH

Поскольку Tkinter практически не имеет документации на Python, я искал и нашел несколько советов TCL, чтобы вывести новый класс и подавить функции insert и delete .

Итак, я попробовал так:

class roText(tk.Text):
    def insert(self,*args,**kwargs):
        print(" Hey  - Im inside roText.insert")
        pass
    def delete(self,*args,**twargs):
        pass    
    def pInsert(self,*args,**twargs):
        super().insert(*args,**twargs)

К сожалению, это не сработало. Очевидно, tkinter не использует эти функции вставки и удаления, когда конечный пользователь вводит / удаляет код. Возможно, эти вставки / удаления TCL являются чем-то другим, и я что-то потерял в переводе с TCL и суахили. Какие функции использует tkinter.Text для редактирования текста конечным пользователем? Надеюсь, они не внутренние ...

Итак, есть ли способ изменить виджет Текст, чтобы запретить только редактирование конечным пользователем? Есть ли способ сделать это без погружения внутрь и переопределения внутреннего кода Tkinter, чтобы материал не сломался в следующих выпусках Tkinter?

Глядя в окно оболочки Idle, я вижу, что им удалось отменить изменения (за исключением последней строки). Так что есть способ. Но что это и как дорого?

Ответы [ 3 ]

3 голосов
/ 01 апреля 2012

Извините, что поднял старый вопрос, но я тоже искал ответ на этот вопрос и, наконец, нашел решение.Решение, которое я нашел, включает в себя переопределение привязок клавиш, когда текстовый виджет имеет фокус и довольно прост.Найдено здесь .

Чтобы переопределить привязки виджета, есть функция привязки, в которой вы передаете строку того, что должно быть переопределено, и новую функцию, которую хотите вызвать.

    self.txtBox.bind("<Key>", self.empty)

Где-то еще в классе вам нужно определить функцию для обработки события.

    def empty(self, event):
        return "break"

Возвращая строку «break», обработчик события знает, что она останавливается после вашей функциивместо продолжения действия по умолчанию.

Надеюсь, это ответит на ваш вопрос.Приветствия.

2 голосов
/ 16 октября 2011

Причина, по которой состояние disabled не работает на Mac, заключается в том, что оно отключает привязку, которая придает фокус виджету. Без фокуса подсветка на Mac не отображается. Если вы установите состояние disabled, но затем назначите привязку для <ButtonPress-1>, чтобы явно установить фокус на отключенном текстовом виджете, вы можете выбрать и скопировать текст, и подсветка отобразится.

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

Чтобы ответить на ваш вопрос о том, действительно ли виджет использует методы insert и delete: методы реального базового виджета - это то, что используют привязки по умолчанию, поэтому их переопределение в подклассе не имеет никакого эффекта. Вам нужно будет повторить все привязки по умолчанию, чтобы это работало. Это выполнимо, но много работы.

К сожалению, это та область, где программирование в Tcl действительно блестяще, потому что вы можете просто отключить команды insert и delete виджета. Конечно, вы можете сделать это непосредственно в Tkinter, так как в конечном итоге он выполняет код tcl, чтобы выполнить все, но это потребует написания некоторого кода tcl, который не очень удачное решение с точки зрения кодера Python.

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

Вот простой пример, который работает путем явной установки фокуса на нажатие кнопки мыши. С помощью этого кода я могу щелкнуть и провести пальцем, чтобы выбрать регион, или дважды или трижды щелкнуть, чтобы выбрать слова и строки:

import Tkinter as tk

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.text = tk.Text(width=40, height=20)
        self.text.bind("<1>", self.set_focus)
        self.text.insert("end", "\n".join(dir(tk.Tk)))
        self.text.configure(state="disabled")
        self.text.pack(fill="both", expand=True)

    def set_focus(self, event):
        '''Explicitly set focus, so user can select and copy text'''
        self.text.focus_set()

if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()
0 голосов
/ 30 октября 2011

@ BryanOakley Мне потребовалось некоторое время, чтобы проверить ваше предложение, так как у меня нет Mac.К сожалению, реализация Python для Mac глючит.Я добавил фокус, т.е. моя функция отключения, которую я вызываю после создания окна и вставки текста, теперь вызывает сначала:

self.txt['state'] = 'disabled'

, а затем

self.txt.focus_set()

.Вы предложили.

Это "вроде" сработало.То есть: при выделении текста (щелчок и перетаскивание или двойной щелчок) подсветка работает чаще времени.У Python должны быть какие-то плохие ссылки на память или такие ошибки: иногда подсветка сначала не работает, затем она начинает работать (в том же окне) после повторного нажатия.Иногда, когда программа вызывается, она работает прямо с места событий.Иногда выбор с помощью клавиши Shift-rightArrow будет работать, но выбор с помощью мыши не будет.Затем снова начинает работать.Или он будет нормально работать в одном окне, но не в другом (оба класса), затем начинает работать во всех окнах ... и т. Д.

Хорошо, что добавление фокуса не повлиялоПлохо для Windows (т.е. все работает нормально, так как без фокуса. Думаю, на данный момент я просто надеюсь, что будущий / следующий выпуск Python для Mac исправит эти ошибки ..

Кстати, кажется, что Mac немногосироты для Python. Реализация гораздо страшнее, чем для Windows. Я имею в виду, что шрифты выглядят хуже, кнопки и т. д.

В любом случае. Спасибо за вашу помощь и предложение использовать фокус для Mac.

...