如何将图像调整大小以适应标签大小?(Python)

5
我的目标是创建一个随机国家生成器,并显示选择的国家的国旗。但是,如果图像文件大于标签的预定大小,则只会显示部分图像。是否有一种方法可以调整图像大小以适合标签?(我看到的所有类似问题的答案都提到了PIL或Image模块。我测试过它们两个,结果都出现了这个错误:

Traceback (most recent call last): File "C:\python\country.py", line 6, in import PIL ImportError: No module named 'PIL'

以下是我的代码,如果有帮助的话:

import tkinter
from tkinter import *
import random

flags = ['England','Wales','Scotland','Northern Ireland','Republic of Ireland']

def newcountry():

    country = random.choice(flags)
    flagLabel.config(text=country)
    if country == "England":
        flagpicture.config(image=England)
    elif country == "Wales":
        flagpicture.config(image=Wales)
    elif country == "Scotland":
        flagpicture.config(image=Scotland)
    elif country == "Northern Ireland":
        flagpicture.config(image=NorthernIreland)
    else:
        flagpicture.config(image=Ireland)

root = tkinter.Tk()
root.title("Country Generator")

England = tkinter.PhotoImage(file="england.gif")
Wales = tkinter.PhotoImage(file="wales.gif")
Scotland = tkinter.PhotoImage(file="scotland.gif")
NorthernIreland = tkinter.PhotoImage(file="northern ireland.gif")
Ireland = tkinter.PhotoImage(file="republic of ireland.gif")
blackscreen = tkinter.PhotoImage(file="black screen.gif")

flagLabel = tkinter.Label(root, text="",font=('Helvetica',40))
flagLabel.pack()

flagpicture = tkinter.Label(root,image=blackscreen,height=150,width=150)
flagpicture.pack()

newflagButton = tkinter.Button(text="Next Country",command=newcountry)
newflagButton.pack()

这段代码除了只显示图像的一部分之外,运行得非常好。是否有一种方法可以在代码本身内调整图像的大小?(我使用的是Python 3.5.1)

3个回答

3
如果您尚未安装PIL,请先进行安装。
pip install pillow

安装后,现在可以从PIL导入:

from PIL import Image, ImageTk

Tk的PhotoImage只能显示.gif格式的图片,而PIL的ImageTk可以让我们在tkinter中显示各种图片格式,并且PIL的Image类有一个resize方法,我们可以用它来调整图片大小。
我简化了你的代码。
您可以调整图像大小,然后只需配置标签,标签将扩展为图像的大小。如果您给标签指定了特定的高度和宽度,比如height=1width=1,然后将图像调整为500x500并配置小部件。它仍然会显示一个1x1的标签,因为您已经明确设置了这些属性。
在下面的代码中,修改字典时,在迭代字典时修改是不可以的。dict.items()返回字典的副本。
有多种方法可以做到这一点,我只是认为字典在这里很方便。 链接到超出高度/宽度限制的图像-kitty.gif
from tkinter import *
import random
from PIL import Image, ImageTk

WIDTH, HEIGHT = 150, 150
flags = {
    'England': 'england.gif',
    'Wales': 'wales.gif', 
    'Kitty': 'kitty.gif'
}

def batch_resize():

    for k, v in flags.items():
        v = Image.open(v).resize((WIDTH, HEIGHT), Image.ANTIALIAS)
        flags[k] = ImageTk.PhotoImage(v)

def newcountry():

    country = random.choice(list(flags.keys()))
    image = flags[country]
    flagLabel['text'] = country
    flagpicture.config(image=image)

if __name__ == '__main__':

    root = Tk()
    root.configure(bg='black')

    batch_resize()

    flagLabel = Label(root, text="", bg='black', fg='cyan', font=('Helvetica',40))
    flagLabel.pack()

    flagpicture = Label(root)
    flagpicture.pack()

    newflagButton = Button(root, text="Next Country", command=newcountry)
    newflagButton.pack()
    root.mainloop()

1
你可以使用PIL(pillow模块)来调整图片大小。但是为了将图像调整为小部件大小,您可以执行以下操作。(假设您熟悉基本的tkinter语法结构)
your_widget.update() #We are calling the update method in-order to update the 
#widget size after it's creartion, Other wise, it will just print '1' and '1' 
#rather than the pixel size.

height=your_widget.winfo_height()
width=your_widget.winfo_width()
print(height,weight)

现在你可以使用高度和宽度信息创建一个新的图像,以便将其完美地调整到您的小部件大小。

但是,如果您已经创建了图像,则可以使用PIL模块将图像调整为所需大小。

首先打开您的图像:

flag_temp = Image.open("file location")

下一步将图像调整为您所需的大小。
flag_new = flag_temp.resize((10,10))# example size

制作您的最终图像以添加到您的小部件中。
flag_final = ImageTk.PhotoImage(flag_new)

现在您可以在小部件中使用“flag final”变量。

如果您的应用程序需要在任何时候调整大小,则可以使用第一个代码段中创建的高度和宽度变量来动态调整图像大小,但是您应该确保定期调用该函数以更新它。

您还应该在(10,10)的位置传入高度和宽度变量,类似于这样。

flag_new = flag_temp.resize((height,widht)

希望这个对您有所帮助,我觉得答案有点长,如果您有任何问题,请在下面评论。

1

我们不再随机选择一个国家来显示其国旗,而是遍历按键排序的国旗字典。与随机选择必然重复国旗不同,这种方案按字母顺序运行所有国家。同时,我们根据根窗口的宽度和高度乘以比例因子将所有图像调整为固定的像素大小。以下是代码:

import  tkinter as tk
from PIL import Image, ImageTk

class   Flags:

    def __init__(self, flags):
        self.flags = flags
        self.keyList = sorted(self.flags.keys()) # sorted(flags)
        self.length = len(self.keyList)
        self.index = 0

    def resize(self, xy, scale):
        xy = [int(x * y) for (x, y) in zip(xy, scale)]
        for k, v in self.flags.items():
            v = Image.open(r'C:/Users/user/Downloads/' + v)
            v = v.resize((xy[0], xy[1]), Image.ANTIALIAS)
            self.flags[k] = ImageTk.PhotoImage(v)

    def newCountry(self, lbl_flag, lbl_pic):
        country = self.keyList[self.index]
        lbl_flag["text"] = country
        img = self.flags[country]
        lbl_pic.config(image = img)
        self.index = (self.index + 1) % self.length # loop around the flags dictionary

def rootSize(root):
    # Find the size of the root window
    root.update_idletasks()
    width = int(root.winfo_width() * 1.5)      #   200 * m
    height = int(root.winfo_height() * 1.0)    #   200 * m
    return width, height

def centerWsize(root, wh):
    root.title("Grids layout manager")
    width, height = wh
    # Find the (x,y) to position it in the center of the screen
    x = int((root.winfo_screenwidth() / 2) - width/2)
    y = int((root.winfo_screenheight() / 2) - height/2)
    root.geometry("{}x{}+{}+{}".format(width, height, x, y))

if __name__ == "__main__":

    flags = {
        "Republic of China": "taiwan_flag.png",
        "United States of America": "america_flag.gif",
        "America": "america_flag.png",
    }

    root = tk.Tk()
    wh = rootSize(root)
    centerWsize(root, wh)
    frame = tk.Frame(root, borderwidth=5, relief=tk.GROOVE)
    frame.grid(column=0, row=0, rowspan=3)
    flag = Flags(flags)
    zoom = (0.7, 0.6)   # Resizing all the flags to a fixed size of wh * zoom
    flag.resize(wh, zoom)
    lbl_flag = tk.Label(frame, text = "Country name here", bg = 'white', fg = 'magenta', font = ('Helvetica', 12), width = 30)
    lbl_flag.grid(column = 0, row = 0)
    pic_flag = tk.Label(frame, text = "Country flag will display here")
    pic_flag.grid(column = 0, row = 1)
    btn_flag = tk.Button(frame, text = "Click for next Country Flag",
                         bg = "white", fg = "green", command = lambda : flag.newCountry(lbl_flag, pic_flag))
    btn_flag.grid(column = 0, row = 2)

    root.mainloop()

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