Показать большое изображение с помощью полосы прокрутки в Python
Я хотел бы отобразить изображение с помощью tkinter (Python 3). Изображение очень длинное. Поэтому я хотел бы добавить вертикальную полосу прокрутки. Вот что я попробовал:
(на основе этого вопроса: полосы прокрутки для изображения.jpg на холсте Tkinter в Python)
import tkinter
import PIL.Image, PIL.ImageTk
# Create a window
window = tkinter.Tk()
frame = tkinter.Frame(window, bd=2) # relief=SUNKEN)
frame.grid_rowconfigure(0, weight=1)
frame.grid_columnconfigure(0, weight=1)
xscrollbar = tkinter.Scrollbar(frame, orient=tkinter.HORIZONTAL)
xscrollbar.grid(row=1, column=0, sticky=tkinter.E+tkinter.W)
yscrollbar = tkinter.Scrollbar(frame)
yscrollbar.grid(row=0, column=1, sticky=tkinter.N+tkinter.S)
canvas = tkinter.Canvas(frame, bd=0, xscrollcommand=xscrollbar.set, yscrollcommand=yscrollbar.set)
canvas.grid(row=0, column=0, sticky=tkinter.N+tkinter.S+tkinter.E+tkinter.W)
canvas.config(scrollregion=canvas.bbox(tkinter.ALL))
File = "FILEPATH"
img = PIL.ImageTk.PhotoImage(PIL.Image.open(File))
canvas.create_image(0,0,image=img, anchor="nw")
xscrollbar.config(command=canvas.xview)
yscrollbar.config(command=canvas.yview)
frame.pack()
window.mainloop()
Я получаю следующее:
Я могу построить изображение, но полосы прокрутки не работают. Они просто серые и не функционируют.
Любая помощь будет оценена!
3 ответа
Если вам нужен виджет с изображением с прокруткой, то лучшим способом было бы создать класс изображения с прокруткой, который будет упорядочен и будет выглядеть лучше для вашего кода. Так что я создал класс для того же, а также добавил связывание <MouseWheel>
так что можно прокручивать их мышью, чтобы просматривать изображение более удобно.
Вот пример кода
import tkinter
from PIL import ImageTk, Image
class ScrollableImage(tkinter.Canvas):
def __init__(self, master=None, **kw):
self.image = kw.pop('image', None)
super(ScrollableImage, self).__init__(master=master, **kw)
self['highlightthickness'] = 0
self.propagate(0) # wont let the scrollbars rule the size of Canvas
self.create_image(0,0, anchor='nw', image=self.image)
# Vertical and Horizontal scrollbars
self.v_scroll = tkinter.Scrollbar(self, orient='vertical', width=6)
self.h_scroll = tkinter.Scrollbar(self, orient='horizontal', width=6)
self.v_scroll.pack(side='right', fill='y')
self.h_scroll.pack(side='bottom', fill='x')
# Set the scrollbars to the canvas
self.config(xscrollcommand=self.h_scroll.set,
yscrollcommand=self.v_scroll.set)
# Set canvas view to the scrollbars
self.v_scroll.config(command=self.yview)
self.h_scroll.config(command=self.xview)
# Assign the region to be scrolled
self.config(scrollregion=self.bbox('all'))
self.focus_set()
self.bind_class(self, "<MouseWheel>", self.mouse_scroll)
def mouse_scroll(self, evt):
if evt.state == 0 :
# self.yview_scroll(-1*(evt.delta), 'units') # For MacOS
self.yview_scroll( int(-1*(evt.delta/120)) , 'units') # For windows
if evt.state == 1:
# self.xview_scroll(-1*(evt.delta), 'units') # For MacOS
self.xview_scroll( int(-1*(evt.delta/120)) , 'units') # For windows
# --------- Example and testing ---------
# This will be true only if the file is not imported as a package.
if __name__ == "__main__":
root = tkinter.Tk()
img = Image.open('test.jpg')
img = ImageTk.PhotoImage(img)
ScrollableImage(root, image=img, width=200, height=200).pack()
root.mainloop()
Как пользоваться классом?
Лечить ScrollableImage
Класс как виджет tkinter и использовать так же, как вы используете любой другой виджет tkinter, так как каждый другой виджет является классом самостоятельно, если вы видите исходный код tkinter.
Есть разные способы, с помощью которых вы можете использовать ScrollableImage
,
Сохраните вышеуказанный код в новом
<name>.py
(например: scrollimage.py") файл в виде пакета в том же каталоге, а затем импортировать в основной класс, напримерfrom scrollimage import ScrollableImage
а затем использовать его как обычный виджет.Или вы можете сохранить
ScrollableImage
Класс в верхней части после импорта вашего основного файла и использовать его, как обычно.
Пример:
import tkinter as tk
# Import the package if saved in a different .py file else paste
# the ScrollableImage class right after your imports.
from scrollimage import ScrollableImage
root = tk.Tk()
# PhotoImage from tkinter only supports:- PGM, PPM, GIF, PNG format.
# To use more formats use PIL ImageTk.PhotoImage
img = tk.PhotoImage(file="logo.png")
show_image = ScrollableImage(root, image=img)
show_image.pack()
root.mainloop()
Связка <MouseWheel>
нужны некоторые изменения на окнах, таких как разделить event.delta
на 120. На MacOS никаких изменений не требуется. А на X11 нужно связать оба <Button-4>
, <Button-5>
а также разделить event.delta
на 120
Привязка колесика мыши Tkinter
Для более подробной информации о связывании
<MouseWheel>
и как это работает на разных платформах можете проверить по вышеуказанной ссылке.Лучший способ структурировать приложение tkinter.
Вы можете обратиться к приведенной выше ссылке, чтобы подробно узнать о том, как правильно применять oops в tkinter. Когда вы используете ООП, вы всегда можете унаследовать любой виджет tkinter и изменить его, чтобы сделать новые виджеты и полезные классы, которые помогут вам сделать приложение с tkinter лучше.
Установите область прокрутки холста после рисования изображения:
canvas.create_image(0, 0, image=img, anchor="nw")
canvas.config(scrollregion=canvas.bbox(tkinter.ALL))
Поместите строку:
canvas.config(scrollregion=canvas.bbox(tkinter.ALL))
после:
canvas.create_image(0,0,image=img, anchor="nw")
или холст не включает изображение в scrollregion.