tkinter: использование полос прокрутки на холсте

Я пытаюсь сделать холст прокручиваемым. Однако, как только я пытаюсь настроить полосы прокрутки для работы с холстом, tkinter, похоже, полностью игнорирует размеры, которые я изначально установил для своего холста. Я пробовал упаковать их все в фрейм, установив холст для заполнения фрейма, а затем установив размер фрейма, но это представляет ту же проблему, если я не установил фрейм для заполнения окна, а это не то, что я хочу . По сути, мне нужен холст фиксированного размера с полосами прокрутки на нем. Мой текущий код выглядит так (в Python 3.1):

from tkinter import *
root=Tk()
frame=Frame(root,width=300,height=300)
frame.grid(row=0,column=0)
canvas=Canvas(frame,bg='#FFFFFF',width=300,height=300,scrollregion=(0,0,500,500))
hbar=Scrollbar(canvas,orient=HORIZONTAL)
hbar.pack(side=BOTTOM,fill=X)
hbar.config(command=canvas.xview)
vbar=Scrollbar(canvas,orient=VERTICAL)
vbar.pack(side=RIGHT,fill=Y)
vbar.config(command=canvas.yview)
canvas.config(width=300,height=300)
canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set)
canvas.pack(side=LEFT,expand=True,fill=BOTH)

root.mainloop()

person Robert Mastragostino    schedule 11.10.2011    source источник


Ответы (1)


Ваши полосы прокрутки должны иметь в качестве родительского элемента Frame, а не Canvas:

from tkinter import *
root=Tk()
frame=Frame(root,width=300,height=300)
frame.pack(expand=True, fill=BOTH) #.grid(row=0,column=0)
canvas=Canvas(frame,bg='#FFFFFF',width=300,height=300,scrollregion=(0,0,500,500))
hbar=Scrollbar(frame,orient=HORIZONTAL)
hbar.pack(side=BOTTOM,fill=X)
hbar.config(command=canvas.xview)
vbar=Scrollbar(frame,orient=VERTICAL)
vbar.pack(side=RIGHT,fill=Y)
vbar.config(command=canvas.yview)
canvas.config(width=300,height=300)
canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set)
canvas.pack(side=LEFT,expand=True,fill=BOTH)

root.mainloop()

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

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

person Shish    schedule 12.10.2011
comment
Почему мы должны упаковывать холст в последнюю очередь? Я заметил, что когда я упаковываю холст перед любой из полос прокрутки, он в конечном итоге перекрывает горизонтальную полосу прокрутки - я только начал использовать tkinter, но я думал, что этот пакет не будет перекрывать материал. Спасибо - person Lanfear; 26.12.2015
comment
А ядро ​​такое scrollregion=(0,0,500,500), без него все работать не может !! - person ch271828n; 10.08.2016
comment
@Bryan Oakley, почему вы устанавливаете ширину и высоту холста с помощью .config, когда вы уже установили их при создании с помощью canvas=Canvas(...)? - person Korzak; 25.03.2019
comment
@Korzak: Не знаю. Я не писал этот код. Нет причин для этого. - person Bryan Oakley; 25.03.2019
comment
Хорошо спасибо. @BryanOakley, знаете ли вы, почему, когда я использовал этот код, он будет прокручиваться только вниз, а не вверх с помощью колеса мыши? Я могу задать новый вопрос, если так будет лучше. Спасибо. - person Korzak; 25.03.2019
comment
@Korzak: это должен быть новый вопрос. Прежде чем спросить, поищите на этом сайте похожие вопросы. На этом сайте есть несколько вопросов, связанных с колесом мыши. - person Bryan Oakley; 26.03.2019
comment
есть ли возможность показать полосу прокрутки внутри области холста с помощью grid ()? - person Mathan; 29.07.2020
comment
По какой-то причине, когда я использую этот скрипт с привязками к холсту, как у B1-Motion, и все такое, кажется, что его event.x и event.y основаны на координатах окна, а не на координатах холста @BryanOakley, знаете ли вы, почему это может быть так. - person Matrix Programmer; 02.05.2021
comment
Хорошо, неважно, так что для тех, у кого может быть проблема с координатами окна, координаты окна из event.x и event.y могут быть преобразованы в координаты холста с помощью функций холста canvas.canvasx и canvas.canvasy. - person Matrix Programmer; 02.05.2021
comment
Также я думаю, что вместо scrollregion = (0, 0, 500, 500) scrollregion = canvas.bbox ('all') будет более общим решением. - person Matrix Programmer; 02.05.2021