Показать большое изображение с помощью полосы прокрутки в Python - PullRequest
3 голосов
/ 08 мая 2019

Я хотел бы отобразить изображение с помощью 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()

Я получаю следующее:

Я могу построить изображение, но полосы прокрутки не работают. Они просто серые и не функционируют.

* +1012 *enter image description here

Буду признателен за любую помощь!

Ответы [ 3 ]

3 голосов
/ 08 мая 2019

Установите область прокрутки холста после вы рисуете изображение:

canvas.create_image(0, 0, image=img, anchor="nw")
canvas.config(scrollregion=canvas.bbox(tkinter.ALL))
3 голосов
/ 08 мая 2019

Если вам нужен виджет с прокручиваемым изображением, то лучшим способом было бы создать класс прокручиваемого изображения, который будет упорядочен и будет выглядеть лучше в вашем коде. Таким образом, я создал класс для того же самого и также добавил связывание <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.

  1. Сохраните приведенный выше код в новый <name>.py (например, "scrollimage.py") файл в виде пакета в том же каталоге, а затем импортируйте его в основной класс, например from scrollimage import ScrollableImage а затем используйте его как обычный виджет.

  2. Или вы можете сохранить класс 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

    Более подробную информацию о bind <MouseWheel> и о том, как он работает на разных платформах, можно найти по ссылке выше.

  • Лучший способ структурировать приложение tkinter.

    Вы можете обратиться к приведенной выше ссылке, чтобы подробно узнать о том, как правильно применять oops в tkinter. Когда вы используете ООП, вы всегда можете унаследовать любой виджет tkinter и изменить его, чтобы сделать новые виджеты и полезные классы, которые помогут вам сделать приложение с tkinter лучше.

3 голосов
/ 08 мая 2019

Поставьте строку:

canvas.config(scrollregion=canvas.bbox(tkinter.ALL))

после:

canvas.create_image(0,0,image=img, anchor="nw")

или холст не включает изображение в область прокрутки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...