在不破坏 tkinter 布局的情况下调整图像大小
Resize an image without breaking the layout in tkinter
好的,所以我有一个问题,并且尝试了太长时间来解决它。我不知道如何在不破坏布局的情况下调整图像大小。在情况 (1) 中,它填满了整个 space,从而破坏了我的布局,我认为这是因为我在绑定到 <Configure>
事件的函数中调用了 configure
函数。在情况 (2) 中,我可以调整图像大小,但我在缩放后的图像周围有一个巨大的边框,这会破坏布局。我什至尝试使用 Canvas
而不是 Label
,但仅绘制 Canvas
会破坏布局,因为它占用了太多 space 并将所有内容向右移动。
想法如何解决?
from tkinter import *
from PIL import ImageTk, Image
global image_label, image_ref
def main():
global image_label
root = Tk()
root.geometry("600x400")
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
content_frame = Frame(root, bg="#FF0000")
content_frame.grid(row=0, column=0, sticky="news")
column_ratio = [10,25,10,45,10]
row_ratio = [10,80,10]
for col_idx in range(5):
content_frame.grid_columnconfigure(col_idx, weight=column_ratio[col_idx])
for row_idx in range(3):
content_frame.grid_rowconfigure(row_idx, weight=row_ratio[row_idx])
image_label = Label(content_frame, bg="#00FF00")
image_label.grid(row=1, column=1, sticky="news")
#image_label.bind("<Configure>", resize_configure) # <--- (1)
second_label = Label(content_frame, bg="#0000FF", text="Label on the right")
second_label.grid(row=1, column=3, sticky="news")
second_label.bind("<Button-1>", resize_click) # <--- (2)
root.mainloop()
def resize(size, label):
global image_ref
image = Image.open("test.png").resize(size, Image.ANTIALIAS)
image_ref = ImageTk.PhotoImage(image)
label.configure(image=image_ref)
def resize_configure(event):
global image_label
size = (event.width, event.height)
resize(size, image_label)
def resize_click(event):
global image_label
image_label.update()
size = (image_label.winfo_width(), image_label.winfo_height())
resize(size, image_label)
if __name__ == "__main__":
main()
Case 1 as an image
Case 2 as an image
How it should look like
您可以使用 place()
而不是 grid()
:
import tkinter as tk
from PIL import Image, ImageTk
base_img = Image.open('test.png')
def on_label_resize(event):
lbl = event.widget
img = ImageTk.PhotoImage(base_img.resize((event.width, event.height)))
lbl.config(image=img)
lbl.image = img
def main():
root = tk.Tk()
root.geometry('640x400')
img_lbl = tk.Label(root, image=None, bg='#00ff00')
img_lbl.place(relx=.1, rely=.1, relwidth=.25, relheight=.8)
img_lbl.bind('<Configure>', on_label_resize)
txt_lbl = tk.Label(root, text='Label on the right', bg='#0000ff')
txt_lbl.place(relx=.45, rely=.1, relwidth=.45, relheight=.8)
root.mainloop()
if __name__ == '__main__':
main()
好的,所以我有一个问题,并且尝试了太长时间来解决它。我不知道如何在不破坏布局的情况下调整图像大小。在情况 (1) 中,它填满了整个 space,从而破坏了我的布局,我认为这是因为我在绑定到 <Configure>
事件的函数中调用了 configure
函数。在情况 (2) 中,我可以调整图像大小,但我在缩放后的图像周围有一个巨大的边框,这会破坏布局。我什至尝试使用 Canvas
而不是 Label
,但仅绘制 Canvas
会破坏布局,因为它占用了太多 space 并将所有内容向右移动。
想法如何解决?
from tkinter import *
from PIL import ImageTk, Image
global image_label, image_ref
def main():
global image_label
root = Tk()
root.geometry("600x400")
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
content_frame = Frame(root, bg="#FF0000")
content_frame.grid(row=0, column=0, sticky="news")
column_ratio = [10,25,10,45,10]
row_ratio = [10,80,10]
for col_idx in range(5):
content_frame.grid_columnconfigure(col_idx, weight=column_ratio[col_idx])
for row_idx in range(3):
content_frame.grid_rowconfigure(row_idx, weight=row_ratio[row_idx])
image_label = Label(content_frame, bg="#00FF00")
image_label.grid(row=1, column=1, sticky="news")
#image_label.bind("<Configure>", resize_configure) # <--- (1)
second_label = Label(content_frame, bg="#0000FF", text="Label on the right")
second_label.grid(row=1, column=3, sticky="news")
second_label.bind("<Button-1>", resize_click) # <--- (2)
root.mainloop()
def resize(size, label):
global image_ref
image = Image.open("test.png").resize(size, Image.ANTIALIAS)
image_ref = ImageTk.PhotoImage(image)
label.configure(image=image_ref)
def resize_configure(event):
global image_label
size = (event.width, event.height)
resize(size, image_label)
def resize_click(event):
global image_label
image_label.update()
size = (image_label.winfo_width(), image_label.winfo_height())
resize(size, image_label)
if __name__ == "__main__":
main()
Case 1 as an image
Case 2 as an image
How it should look like
您可以使用 place()
而不是 grid()
:
import tkinter as tk
from PIL import Image, ImageTk
base_img = Image.open('test.png')
def on_label_resize(event):
lbl = event.widget
img = ImageTk.PhotoImage(base_img.resize((event.width, event.height)))
lbl.config(image=img)
lbl.image = img
def main():
root = tk.Tk()
root.geometry('640x400')
img_lbl = tk.Label(root, image=None, bg='#00ff00')
img_lbl.place(relx=.1, rely=.1, relwidth=.25, relheight=.8)
img_lbl.bind('<Configure>', on_label_resize)
txt_lbl = tk.Label(root, text='Label on the right', bg='#0000ff')
txt_lbl.place(relx=.45, rely=.1, relwidth=.45, relheight=.8)
root.mainloop()
if __name__ == '__main__':
main()