如何使用 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()
我想在 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()