如何使用 PIL 在 tkinter 中将图像居中

How to center an image in tkinter with PIL

我想在 tkinter 中将图像居中,但我做不到这是我的代码

def newsetup(filelocation):
    global width, height
    
    for widgets in root.winfo_children():
        widgets.destroy()

    stage = Canvas(root, width = 1000, height = 700, highlightbackground = 'red', highlightthickness = 2)
    stage.pack()

    imgtk = ImageTk.PhotoImage(Image.open(filelocation)) 
    stage.create_image(stage.winfo_width() + 2, stage.winfo_height() + 2, image = imgtk, anchor = CENTER)
    stage.image = imgtk

如果你想以canvas为中心,那么你需要

stage.winfo_width()/2, stage.winfo_height()/2

(即使没有 anchor=,默认值为 center

但是如果你把图像放在它前面 运行s mainloop() 然后 stage.winfo_width() stage.winfo_height() 给出 0,0 而不是预期的 width, height (因为mainloop 创建 window 并设置小部件的所有尺寸)并且它可能需要 root.update() 到 运行 mainloop 一次,它将计算所有尺寸。

import tkinter as tk
from PIL import ImageTk, Image

root = tk.Tk()

stage = tk.Canvas(root, width=1000, height=700)
stage.pack()

root.update()  # force `mainloop()` to calculate current `width`, `height` for canvas
               # and later `stage.winfo_width()` `stage.winfo_height()` will get correct values instead `0`
    
#imgtk = ImageTk.PhotoImage(Image.open('lenna.png'))
imgtk = ImageTk.PhotoImage(file='lenna.png')

stage.create_image((stage.winfo_width()/2, stage.winfo_height()/2), image=imgtk, anchor='center')
stage.image = imgtk

root.mainloop()

结果:


图片 Lenna 来自维基百科。


编辑:

如果您想在调整 window 大小时使其保持居中,那么您可以将事件 <Configure> 绑定到 canvas,它将执行分配的功能 - 并且它可以移动图像。

但它需要image ID,你可以在创建图像时获得

img_id = stage.create_image(...)

因为 <Configure> 在创建 window 时执行,所以代码不需要 root.update() 因为 on_resize() 会在开始时设置正确的位置。

import tkinter as tk
from PIL import ImageTk, Image

# --- functions ---

def on_resize(event):
    # it respects anchor
    x = event.width/2  
    y = event.height/2
    stage.coords(img_id, x, y)  
    
    # it DOESN'T respects anchor so you have to add offset
    #x = (event.width - imgtk.width())/2  
    #y = (event.height - imgtk.height())/2
    #stage.moveto(img_id, x, y)  # doesn't respect anchor

    #stage.itemconfigure(img_id, ...)

# --- main ---

root = tk.Tk()

stage = tk.Canvas(root, width=1000, height=700)
stage.pack(fill='both', expand=True)

#root.update()  # force `mainloop()` to calculate current `width`, `height` for canvas
               # and later `stage.winfo_width()` `stage.winfo_height()` will get correct values instead `0`
    
#imgtk = ImageTk.PhotoImage(Image.open('lenna.png'))
imgtk = ImageTk.PhotoImage(file='lenna.png')

img_id = stage.create_image((stage.winfo_width()/2, stage.winfo_height()/2), image=imgtk, anchor='center')
stage.image = imgtk

stage.bind('<Configure>', on_resize)  # run function when Canvas change size

root.mainloop()