在 Tkinter 中动态调整图像大小

问题描述 投票:0回答:2

我有几个图像需要在 Tkinter 窗口中显示(我可能会使用画布来显示它们 - 可能是标签)。这些图像将占据大约三分之一的屏幕。当用户使用不同尺寸的显示器时,我需要图像屏幕比例保持一致。

因此,假设用户使用小型显示器,图像需要在小屏幕上占据与用户使用大型 4K 显示器相同的照片屏幕比例。

Tkinter 会自动为我执行此操作吗?或者我必须自己实现它 - 如果是这样,这可能吗?

我没有任何代码,因为我不知道从哪里开始。我想我也许可以使用 PIL 或枕头,但我对它们还很陌生。

如有任何帮助,我们将不胜感激,谢谢:)

python-3.x tkinter python-imaging-library tkinter-canvas
2个回答
1
投票

1)您需要获取当前的屏幕分辨率:How do I get Monitor resolution in Python?
2)然后你需要调整图像的大小(如何使用PIL调整图像大小并保持其纵横比?)和/或你的窗口(https://yagisanatode.com/2018/02/23/如何更改 tkinter 和 python-3 中主窗口的大小和位置/)

所以代码应该是这样的:

from win32api import GetSystemMetrics
from Tkinter import Tk

screen_width, screen_height = GetSystemMetrics(0), GetSystemMetrics(1)

root = Tk() # this is your window
root.geometry("{}x{}".format(screen_width//2, screen_height//2)) # set size of you window here is example for 1/2 screen height and width

img = Image.open("picture_name.png", "r") # replace with picture path
width, height = screen_width//4, screen_height//4 # determine widght and height basing on screen_width, screen_height
img.resize((width, height), Image.ANTIALIAS) 

# todo: create more Tkinter objects and pack them into root

root.mainloop()

这应该可以解决您的问题。关于Tkinter的使用,有很多教程,例如:http://effbot.org/tkinterbook/


0
投票

是的,你可以这样做:

import PIL.Image
import tkinter as tk
from PIL import ImageTk
from tkinter.filedialog import askopenfilename

class CanvasImage(tk.Canvas):
    def __init__(self, master: tk.Tk, **kwargs):
        super().__init__(master, **kwargs)

        self.source_image = None
        self.image_id = None
        self.image = None

        self.width, self.height = 0, 0
        self.center_x, self.center_y = 0, 0
        self.bind('<Configure>', self.update_values)
    
    def update_values(self, *_) -> None:
        self.width = self.winfo_width()
        self.height = self.winfo_height()
        self.center_x = self.width//2
        self.center_y = self.height//2

        if self.image is None: return
        self.delete_previous_image()
        self.resize_image()
        self.paste_image()

    def delete_previous_image(self) -> None:
        if self.image is None: return
        self.delete(self.image_id)
        self.image = self.image_id = None

    def resize_image(self) -> None:
        image_width, image_height = self.source_image.size
        width_ratio = self.width / image_width
        height_ratio = self.height / image_height
        ratio = min(width_ratio, height_ratio)

        new_width = int(image_width * ratio)
        new_height = int(image_height * ratio)
        scaled_image = self.source_image.resize((new_width, new_height))
        self.image = ImageTk.PhotoImage(scaled_image)

    def paste_image(self) -> None:
        self.image_id = self.create_image(self.center_x, self.center_y, image=self.image)

    def open_image(self) -> None:
        if not (filename := askopenfilename()): return

        self.delete_previous_image()
        self.source_image = PIL.Image.open(filename)
        self.image = ImageTk.PhotoImage(self.source_image)

        self.resize_image()
        self.paste_image()


class Window(tk.Tk):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.canvas = CanvasImage(self, relief='sunken', bd=2)
        tk.Button(self, text='Abrir imagen', comman=self.canvas.open_image).pack()
        self.canvas.pack(expand=True, fill='both', padx=10, pady=10)


if __name__ == '__main__':
    window = Window()
    window.mainloop()
© www.soinside.com 2019 - 2024. All rights reserved.