Почему этот код заставляет окно Tkinter постоянно изменять размер / увеличиваться автоматически? - PullRequest
2 голосов
/ 23 сентября 2019

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

import tkinter as tk

root = tk.Tk()

canvas = tk.Canvas(root, height=500, width=500)
canvas.pack()

from PIL import Image, ImageTk

def resize_image(event):
    new_width = event.width
    new_height = event.height
    image = copy_of_image.resize((new_width, new_height))
    photo = ImageTk.PhotoImage(image)
    label.configure(image = photo)
    label.image = photo

image = Image.open("*file path to image*")
copy_of_image = image.copy()
photo = ImageTk.PhotoImage(image)
label = tk.Label(canvas, image=photo)
label.bind('<Configure>', resize_image)
label.pack(fill='both', expand='yes')

root.mainloop()

Ответы [ 2 ]

1 голос
/ 23 сентября 2019

Вы вызываете функцию всякий раз, когда виджет меняет размер.В этой функции вы изменяете размер изображения в соответствии с размером метки.Однако вокруг изображения, скорее всего, есть граница или отступы, поэтому метка может немного увеличиться.Поскольку метка увеличивается, она вызывает событие <Configure>, которое снова изменяет размер изображения, что приводит к изменению размера метки, которое вызывает событие <Configure>, которое снова изменяет размер изображения, что приводит к изменению размера метки, ....

Решение состоит в том, чтобы убедиться, что ширина полосы и толщина подсветки равны нулю, и / или изменить размер изображения так, чтобы оно было на пару пикселей меньше метки, чтобы не увеличивать метку.

0 голосов
/ 23 сентября 2019

Хорошо, после некоторого тестирования, я думаю, что нашел решение, которое вы ищете.

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

import tkinter as tk
from PIL import Image, ImageTk


root = tk.Tk()


canvas = tk.Canvas(root, height=500, width=500)
canvas.pack(fill='both', expand=True)
frame = tk.Frame(canvas)
canvas.create_window((0, 0), anchor='nw', window=frame, tags='my_frame')


def resize_image(event):
    canvas.itemconfigure("my_frame", width=event.width, height=event.height)
    image = copy_of_image.resize((event.width, event.height ))
    photo = ImageTk.PhotoImage(image)
    label.configure(image=photo)
    label.image = photo


image = Image.open("*file path to image*")
copy_of_image = image.copy()
photo = ImageTk.PhotoImage(image)
label = tk.Label(frame, image=photo)
label.pack(fill='both', expand=True)
canvas.bind('<Configure>', resize_image)

root.mainloop()

Для решения ООП см. Ниже:

import tkinter as tk
from PIL import Image, ImageTk


class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.canvas = tk.Canvas(self)
        self.frame = tk.Frame(self.canvas)
        self.canvas.pack(fill='both', expand=True)

        image = Image.open('./Images/green.png')
        self.copy_of_image = image.copy()
        photo = ImageTk.PhotoImage(image)
        self.label = tk.Label(self.frame, image=photo)
        self.label.pack(fill='both', expand=True)
        self.label.image = photo

        self.canvas.create_window((0, 0), anchor='nw', window=self.frame, tags='my_frame')
        self.canvas.bind("<Configure>", self.on_canvas_configure)

    def on_canvas_configure(self, event):
        self.canvas.itemconfigure("my_frame", width=event.width, height=event.height)
        image = self.copy_of_image.resize((event.width, event.height))
        photo = ImageTk.PhotoImage(image)
        self.label.configure(image=photo)
        self.label.image = photo


if __name__ == "__main__":
    App().mainloop()
...