Прокрутка холстов

prokrutka holstov Экскурсия по tkinter, часть 2

Однако одна из операций над холстами настолько часто используется в практике, что действительно заслуживает внимания. Как демонстрирует пример 9.14, полосы прокрутки можно перекрестно связывать с холстами, используя те же протоколы, которые ранее использовались для добавления их к виджетам Listbox и Text, но с некоторыми особыми требованиями.

Пример 9.14. PP4E\Gui\Tour\scrolledcanvas.py

“простой компонент холста с вертикальной прокруткой”

from tkinter import *

class ScrolledCanvas(Frame):

def __init__(self, parent=None, color=’brown’):

Frame.__init__(self, parent)

self.pack(expand=YES, fill=BOTH) # сделать растягиваемым

canv = Canvas(self, bg=color, relief=SUNKEN)

canv.config(width=300, height=200) # размер видимой области

canv.config(scrollregion=(0, 0, 300, 1000)) # углы холста canv.config(highlightthickness=0) # без рамки

sbar = Scrollbar(self) sbar.config(command=canv.yview) # связать sbar и canv canv.config(yscrollcommand=sbar.set) # сдвиг одного = сдвиг другого sbar.pack(side=RIGHT, fill=Y) # первым добавлен посл. обрезан

canv.pack(side=LEFT, expand=YES, fill=BOTH) # canv обрезается первым

self.fillContent(canv)

canv.bind(‘<Double-1>’, self.onDoubleClick) # установить обр. события self.canvas = canv

def fillContent(self, canv): # переопределить при

for i in range(10): # наследовании

canv.create_text(150, 50+(i*100), text=’spam’+str(i),fill=’beige’)

def onDoubleClick(self, event): # переопределить при

print(event.x, event.y) # наследовании

print(self.canvas.canvasx(event.x), self.canvas.canvasy(event.y))

if __name__ == ‘__main__’: ScrolledCanvas().mainloop()

Этот сценарий создает окно, изображенное на рис. 9.24. Оно аналогично предыдущим примерам реализации прокрутки, но в модели прокрутки холстов есть две особенности:

Размеры области прокрутки и видимой области

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

Отображение координат в области просмотра в абсолютные координаты

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

Рис. 9.24. Сценарий scrolledcanvas в действии

 

Размеры определяются как параметры настройки. Размер видимой области определяется с помощью параметров холста width и height. Чтобы определить общий размер холста, в параметре scrollregion следует передать кортеж с четырьмя координатами верхнего левого и нижнего правого углов холста. Если размер видимой области не указан, используется размер по умолчанию. Если не задан параметр scrollregion, он принимается по умолчанию равным размеру видимой области. При этом полоса прокрутки становится бесполезной, так как видимая область в этом случае вмещает весь холст целиком.

Пересчет координат осуществляется несколько более сложным образом. Если прокручиваемая видимая область холста оказывается меньше, чем холст в целом, то координаты (X,Y), возвращаемые в объектах событий, представляют собой координаты в видимой области, а не в холсте в целом. Обычно требуется перевести координаты события в координаты холста, для чего они передаются методам canvasx и canvasy прежде чем их можно будет использовать для обработки объектов.

Например, если запустить сценарий реализации прокручиваемого холста и посмотреть на сообщения, выводимые при выполнении двойных щелчков мышью, можно заметить, что координаты события всегда относятся к видимой области, а не холсту в целом:

C:\\PP4E\Gui\Tour> python scrolledcanvas.py

2  0 координаты x,y события, если холст прокручен доверху

2.0 0.0 координаты x,y холста — те же, если нет пикселей границы

150 106

150.0 106.0

299 197

299.0 197.0

3  2 координаты x,y события, если холст прокручен донизу

3.0 802.0 координаты x,y холста — координата y отличается

296 192

296.0 992.0

152 97 при прокрутке в среднюю часть холста

152.0 599.0

16 187

16.0 689.0

Здесь отображаемая координата X видимой области холста всегда совпадает с координатой X всего холста, поскольку видимая область и холст имеют одинаковую ширину 300 пикселей (из-за автоматической установки границ могло бы появиться расхождение в два пикселя, если бы не значение highlightthickness, установленное в сценарии). Обратите внимание, что после щелчка на вертикальной полосе прокрутки отображаемая координата Y видимой области становится отличной от координаты Y холста. Без преобразования координат значение координаты Y события неверно указывало бы на место, находящееся на холсте значительно выше.

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

Как правило, если холст поддерживает возможность прокрутки, то в обработчиках событий, учитывающих позицию, необходимо преобразовывать координаты события в действительные координаты холста. Для некоторых обработчиков это не требуется, если они привязаны к отдельным объектам или виджетам на холсте, а не к самому холсту; в следующих двух разделах показано, что происходит в этом случае.

Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011

Оцените статью
Секреты программирования
Добавить комментарий