В примере 9.11 используются некоторые из этих понятий. Он расширяет пример 9.10, добавляя поддержку четырех наиболее часто используемых операций редактирования — сохранение в файл, удаление и вставка текста и поиск строки — за счет создания подкласса, наследующего класс ScrolledText, с дополнительными кнопками и методами. В виджете Text есть набор готовых привязок клавиш, выполняющих некоторые часто используемые операции редактирования, но они могут оказаться совсем не теми, которые можно было бы ожидать на конкретных платформах. Чаще в текстовом редакторе с графическим интерфейсом предоставляются специальные элементы управления, выполняющие операции редактирования, что более дружественно по отношению к пользователю.
Пример 9.11. PP4E\Gui\Tour\simpleedit.py
за счет наследования добавляет в ScrolledText типичные инструменты редактирования; аналогичного результата можно было бы добиться, применив прием композиции (встраивания); ненадежно! — надмножество функций имеется в PyEdit;
from tkinter import *
from tkinter.simpledialog import askstring
from tkinter.filedialog import asksaveasfilename
from quitter import Quitter
from scrolledtext import ScrolledText # наш, не из библиотеки Python
class SimpleEditor(ScrolledText): # доп. ф—ции смотрите в PyEdit
def __init__(self, parent=None, file=None):
frm = Frame(parent)
frm.pack(fill=X)
Button(frm, text=’Save’, command=self.onSave).pack(side=LEFT)
Button(frm, text=’Cut’, command=self.onCut).pack(side=LEFT)
Button(frm, text=’Paste’, command=self.onPaste).pack(side=LEFT) Button(frm, text=’Find’, command=self.onFind).pack(side=LEFT) Quitter(frm).pack(side=LEFT)
ScrolledText.__init__(self, parent, file=file) self.text.config(font=(‘courier’, 9, ‘normal’))
def onSave(self):
filename = asksaveasfilename() if filename:
alltext = self.gettext() # от начала до конца
open(filename, ‘w’).write(alltext) # сохранить текст в файл
def onCut(self):
text = self.text.get(SEL_FIRST, SEL_LAST) # ошибка, если нет выделения self.text.delete(SEL_FIRST, SEL_LAST) # следует обернуть в try self.clipboard_clear() self.clipboard_append(text)
def onPaste(self): # добавляет текст из буфера
try:
text = self.selection_get(selection=’CLIPBOARD’)
self.text.insert(INSERT, text) except TclError:
pass # не вставлять
def onFind(self):
target = askstring(‘SimpleEditor’, ‘Search String?’) if target:
where = self.text.search(target, INSERT, END) # от позиции курсора if where: # вернуть индекс
print(where)
pastit = where + (‘+%dc’ % len(target)) # индекс за целью #self.text.tag_remove(SEL, ‘1.0’, END) # снять выделение self.text.tag_add(SEL, where, pastit) # выделить найденное self.text.mark_set(INSERT, pastit) # установить метку вставки self.text.see(INSERT) # прокрутить текст
self.text.focus() # выбрать виджет Text
if __name__ == ‘__main__’: if len(sys.argv) > 1: SimpleEditor(file=sys.argv[1]).mainloop() # имя файла в ком. строке else:
SimpleEditor().mainloop() # или нет: пустой виджет
Этот сценарий также был написан с оглядкой на многократное использование — определяемый в нем класс SimpleEditor можно прикрепить или унаследовать в другой реализации графического интерфейса. Однако, как будет разъяснено в конце раздела, данный пример не настолько надежен, как требуется от библиотечного инструмента общего назначения. Тем не менее в нем реализован действующий текстовый редактор, программный код которого переносим и имеет небольшой объем. Если запустить пример как самостоятельный сценарий, он выведет окно, изображенное на рис. 9.19 (здесь он был запущен в Windows). После каждой успешной операции поиска позиции индексов выводятся в stdout — в этом примере логика снятия предыдущего выделения закомментирована, поэтому вторая операция поиска, как видно на рисунке, выделила вторую строку «def», не сняв предыдущее выделение (раскомментируйте эту строку в сценарии, чтобы операция поиска снимала предыдущее выделение):
C:\…\PP4E\Gui\Tour> python simpleedit.py simpleedit.py PP4E scrolledtext
14.4
25.4
Операция сохранения выводит имеющийся в библиотеке tkinter стандартный диалог сохранения, который выглядит естественным в каждой из платформ. На рис. 9.20 изображен этот диалог в Windows 7. Операция поиска тоже выводит стандартный диалог для ввода строки поиска (рис. 9.21); в полноценном редакторе можно было бы сохранить эту строку для повторного поиска (что мы и сделаем в главе 11, в реа-
Рис. 9.19. Сценарий simpleedit в действии
Рис. 9.20. Диалог сохранения файла в Windows
Рис. 9.21. Диалог поиска
лизации редактора PyEdit). Для реализации операции завершения повторно был использован компонент кнопки Quit, реализованный нами в главе 8, — этот код гарантирует, что приложение не может быть завершено без подтверждения.
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011