【问题标题】:Dynamically resize two panels in tkinter在 tkinter 中动态调整两个面板的大小
【发布时间】:2019-04-30 16:07:11
【问题描述】:

我在一个框架中设置了 2 个面板:

frameA = Frame(master)
frameA.pack(side=LEFT, fill=BOTH, expand=YES)
frameB = Frame(master)
frameB.pack(side=RIGHT, fill=BOTH, expand=YES)
recale = 0.4
self.img = ImageTk.PhotoImage(img.resize((int(rescale*width), int(recale*height)), Image.ANTIALIAS)

self.panelA = Label(frameA, image=self.img)
self.pabelA.pack(side=LEFT, fill=BOTH, expand=YES)

self.panelB = Label(frameB, image=self.img)
self.pabelB.pack(side=LEFT, fill=BOTH, expand=YES)

现在,两个面板的大小由我调整为 0.4 倍于原始大小的图像大小决定。如何动态设置rescale,以便当我按下最大化按钮时每个面板的宽度占据主框架的整个宽度(这不是我制作的按钮,而是旁边的小方形按钮来最小化,并在右上角关闭)在 GUI 上?

【问题讨论】:

  • 您能否提供minimal reproducible example 来说明您的问题?
  • 如果您在函数中创建PhotoImage,那么您必须分配给类变量(即self.photo = ImageTk.PhotoImage(img)),因为当分配给局部变量时,存在将PhotoImage 从内存中删除的错误。请参阅页面底部的NotePhotoImage
  • 可以获取屏幕宽度master.winfo_screenwidth()和设置窗口大小master.geometry('{}x{}'.format(x, y))
  • 我已经解决了你的第一条评论,@furas。对于您的第二条评论,我如何使用该信息设置 rescale 以及如何动态设置?
  • 在问题中,您对rescale 只字未提,但关于窗口大小和框架大小。它有所作为。你需要window.widthbind('<Configure>", on_resize)

标签: python tkinter


【解决方案1】:

当您使用 pack(fill=BOTH, expand=YES) 时,tkinter 会自动调整 FrameLabel 的大小以适应窗口 - 因此您不必手动调整它的大小。但它永远不会调整PhotoImageImage 的大小,因此它看起来可能不会调整LabelFrame 的大小。所以你真正的问题可能是“当你改变窗口大小时如何调整图像大小”

使用

root.bind('<Configure>', on_resize)

你可以在窗口改变大小时运行函数,然后你可以生成新图像并替换Label

这个函数不仅会针对 window 执行,还会针对 window 中的每个小部件执行,所以我使用 str(event.widget) == '.' 仅在针对 window 执行时调整它的大小。

import tkinter as tk
from PIL import Image, ImageTk

def on_resize(event):
    global rescaled_img
    global photo

    #print('[DEBUG] on_resize:', event.widget)

    # resize only when root window changes size
    if str(event.widget) == '.':
        # generate new image
        width  = event.width//2 # -2  # -2*border
        height = event.height   # -2  # -2*border
        rescaled_img = original_img.resize((width, height), Image.ANTIALIAS)
        photo = ImageTk.PhotoImage(rescaled_img)

        # replace images in labels
        label_left['image'] = photo
        label_right['image'] = photo

# ---- main ---

# resize at start
original_img = Image.open('image.jpg')
rescale = 0.4
width = int(rescale * original_img.width)
height = int(rescale * original_img.height)
rescaled_img = original_img.resize((width, height), Image.ANTIALIAS)


root = tk.Tk()

photo = ImageTk.PhotoImage(rescaled_img)

label_left = tk.Label(root, image=photo, border=0) # if border > 0 then you have to use `-2*border` in on_resize
label_left.pack(side='left', fill='both', expand=True)

label_right = tk.Label(root, image=photo, border=0) # if border > 0 then you have to use `-2*border` in on_resize
label_right.pack(side='left', fill='both', expand=True)

# resize when window changed size
root.bind('<Configure>', on_resize)

root.mainloop()

我尝试绑定到label,正如您在Tkinter resize background image to window size 中的一些代码中看到的那样,但它不能正常工作 - 一开始它会使图像越来越大,直到窗口填满整个屏幕。或者在开始时它使图像越来越小,直到窗口没有大小。


如果 Label 的边框大于 0,那么您必须从图像大小中减去 2*border

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-25
    • 1970-01-01
    • 2021-06-09
    • 2013-02-19
    • 1970-01-01
    相关资源
    最近更新 更多