在Python的tkinter.ttk中如何使图像居中显示?

3

我正在使用tkinter.ttk创建一个简单的应用程序。我正在创建一个图像查看器应用程序,但在创建应用程序时遇到了一些问题。这是我的代码:

from tkinter import *
from tkinter.ttk import *
from PIL import Image, ImageTk

root = Tk()
root.title("Simple Image Viewer")
style = Style()


root.columnconfigure(0, weight=True)
root.rowconfigure(0, weight=True)

img1 = ImageTk.PhotoImage(Image.open("images/img_1.jpg"))
img2 = ImageTk.PhotoImage(Image.open("images/img_2.jpg"))
img3 = ImageTk.PhotoImage(Image.open("images/img_3.jpg"))

images = [img1, img2, img3]
img_idx = 0


def previous_image():
    global lbl_img
    global images
    global img_idx
    img_idx = img_idx - 1
    if img_idx < 0:
        img_idx = len(images) - 1
    try:
        lbl_img.configure(image=images[img_idx])
    except IndexError:
        img_idx = -1
        lbl_img.configure(image=images[img_idx])
    finally:
        status.configure(text=f"{img_idx + 1} of {len(images)} images.")


btn_back = Button(text="<", command=previous_image)


def forward_image():
    global lbl_img
    global images
    global img_idx
    img_idx = img_idx + 1
    try:
        lbl_img.configure(image=images[img_idx])
    except IndexError:
        img_idx = 0
        lbl_img.configure(image=images[img_idx])
    finally:
        status.configure(text=f"{img_idx + 1} of {len(images)} images.")


btn_forward = Button(text=">", command=forward_image)

lbl_img = Label(image=images[img_idx])

status = Label(root, text=f"{img_idx + 1} of {len(images)} images.", borderwidth=1,
               relief=SUNKEN, anchor="e")
status.grid(row=2, column=0, columnspan=3, stick=W+E)

btn_exit = Button(text="Exit", command=root.quit)
btn_back.grid(row=0, column=0, stick=W)
lbl_img.grid(row=0, column=1)
btn_forward.grid(row=0, column=2, stick=E)
btn_exit.grid(row=1, column=1)

root.mainloop()

当我运行它时,它显示如下: 在小窗口中 当我将其最大化时:在最大化中。 如上图所示,您可以看到图片在两种大小的窗口中都没有居中显示。我的图片必须在小窗口和大窗口中完全居中。请问有谁可以通过查看我的程序来帮助我解决这个问题。
提前感谢您。

1
你只需要将 root.columnconfigure(0, weight=True) 改为root.columnconfigure(1, weight=1) - acw1668
3个回答

3
你可以使用网格布局实现此功能,需要确保左右和上下都获得空间,但是中间不获得空间。例如:
import tkinter as tk

root = tk.Tk()

up = tk.Frame(root)
up.grid(column=0, row=0,columnspan=3,sticky='n')
s1 = tk.Label(up, text='spacer')
s1.pack()

left = tk.Frame(root)
b1 = tk.Button(left, text='B1')
left.grid(column=0,row=1,sticky='w')
b1.pack()

middle = tk.Frame(root)
middle.grid(column=1, row=1)
s2 = tk.Label(middle, text='spacer')
s2.pack()

down = tk.Frame(root)
qb = tk.Button(down, text='Exit', command= root.destroy)
down.grid(column=0, row=2,columnspan=3,sticky='s')
qb.pack()

right = tk.Frame(root)
right.grid(column=2,row=1,sticky='e')
b2 = tk.Button(right, text='B2')
b2.pack()

root.columnconfigure(0,weight=1) #left get space
root.columnconfigure(2,weight=1) #right get space

root.rowconfigure(0, weight=1) #up get space
root.rowconfigure(2, weight=1) #down get space

root.mainloop()

输出: 输入图像说明

如需详细信息,请参见weight在tkinter中的作用


2
我认为有两种解决方案可以解决这个问题。
1. 当你将图像显示到程序中时,你可以使用....place(x=x_coord, y=y_coord, anchor=center)来确保图像设置在程序中心并始终处于中心位置。
提示:在程序开始时设置分辨率,而不是使用网格,您可以使用坐标和锚点来放置您的按钮和图像(我认为)。我没有尝试过使用图像。
2. 另一种可能解决您问题的方法是确定您是否希望程序全屏运行。如果您希望程序保持在一个像第一个参考上那样的漂亮小窗口中,您可以防止用户调整窗口大小。当您最大化窗口时,您没有使图像随着窗口变大而调整大小,所以我相信这样做是可以的。在定义root后的程序开始时... root.resizable(0, 0)。这将防止用户调整窗口大小。

1
没问题。如果您的程序不打算最大化,那么解决方案2应该可以很好地工作,我非常确定。 - Kevin Apetrei
1
如果您想在最大化时更改图像,请尝试搜索如何在tkinter中缩放图像。我找到了一些链接,我认为可能会有所帮助... https://pythonprogramming.altervista.org/tkinter-python-app-to-resize-images-part-1/ 和 https://www.codegrepper.com/code-examples/delphi/how+to+resize+image+in+python+tkinter - Kevin Apetrei

1

我按照您的建议进行了实现,但对于我来说按钮并不完美。我想把按钮放在标签上面,而不是在旁边。这可能吗?

import tkinter as tk

    
root = tk.Tk()
image_list = getfiles()

up = tk.Frame(root)
up.grid(column=0, row=0,columnspan=3,sticky='n')
s1 = tk.Label(up, text='spacer')
s1.pack()

left = tk.Frame(root)
b1 = tk.Button(left, text='B1')
left.grid(column=0,row=1,sticky='w')
b1.pack()

middle = tk.Frame(root)
middle.grid(column=1, row=1)
s2 = tk.Label(middle, text='spacer')
image = Image.open(image_list[current])
photo = ImageTk.PhotoImage(image)
s2['image'] = photo
s2.photo = photo
s2.pack()

down = tk.Frame(root)
qb = tk.Button(down, text='Exit', command= root.destroy)
down.grid(column=0, row=2,columnspan=3,sticky='s')
qb.pack()

right = tk.Frame(root)
right.grid(column=2,row=1,sticky='e')
b2 = tk.Button(right, text='B2')
b2.pack()

root.columnconfigure(0,weight=1) #left get space
root.columnconfigure(2,weight=1) #right get space

root.rowconfigure(0, weight=1) #up get space
root.rowconfigure(2, weight=1) #down get space

root.mainloop()

要将按钮放在与图像相同的位置,您需要使用place()函数。
label = Tkinter.Label(root, compound=Tkinter.TOP)
label.pack()

A=Tkinter.Button(root, text='Previous picture', command=lambda: move(-1))
A.place(relx=0, x=2, y=20,width=130,height=100)
B=Tkinter.Button(root, text='Next picture', command=lambda: move(+1))
B.place(relx=0, x=135, y=20,width=130,height=100)
C=Tkinter.Button(root, text='PRINT', command=root.quit)
C.place(relx=1, x=-130, y=20,width=130,height=100)

move(0)
root.update()
root.mainloop()


我无法理解你说的话。但是这个代码可以运行。我已经测试过了。 - Binamra
1
晚安,我想把按钮放在标签上面,而不是侧边。这可行吗? - virtualsets
你的意思是在spacer标签上方添加一个按钮,然后在上面的框架中添加一个按钮并在标签之前pack它吗? - Binamra
1
我已经放置了解决方案...需要使用place()函数进行定位。 - virtualsets

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接