Python Tkinter 将背景图像调整为窗口大小

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24061099/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 03:53:57  来源:igfitidea点击:

Tkinter resize background image to window size

pythonpython-3.xtkinter

提问by Tomha

Trying to set up a background for my tkinter window. I have a square background image, which fades to black around the edges, and then the main window has a black background. The image is placed over the background, and if the window is wider than it is tall, the image centers itself in the middle over the black background, and it all looks very nice.

试图为我的 tkinter 窗口设置背景。我有一个方形背景图像,它的边缘逐渐变黑,然后主窗口有一个黑色背景。图像放置在背景上,如果窗口的宽度大于高度,则图像将自身居中放置在黑色背景的中间,这样看起来都非常漂亮。

However when the window is smaller than the image in width and height, it puts the center of the image in the center of the window, so you don't see the whole image, and it looks a little odd. Is there a way of resizing the image so that if the largest of the width and height of the window is smaller than the image, the image is adjusted to that size, keeping aspect ratio.

但是当窗口的宽度和高度小于图像时,它会将图像的中心放在窗口的中心,因此您看不到整个图像,看起来有点奇怪。有没有办法调整图像大小,以便如果窗口的宽度和高度中的最大值小于图像,则将图像调整为该尺寸,保持纵横比。

So say the background image is 600x600:

所以说背景图片是600x600

  • In a 800x400window, the image does not resize, and centers itself vertically.
  • In a 500x400window, the image resizes to 500x500, and still centers itself vertically.
  • In a 400x900window, the image does not resize, and centers itself horizontally.
  • 800x400窗口中,图像不会调整大小,而是垂直居中。
  • 500x400窗口中,图像调整为500x500,并且仍然垂直居中。
  • 400x900窗口中,图像不会调整大小,而是水平居中。

The centering functionality is already there, I just need the resize functionality.

居中功能已经存在,我只需要调整大小功能。

Currently what I have is:

目前我所拥有的是:

from tkinter import *

root = Tk()
root.title("Title")
root.geometry("600x600")
root.configure(background="black")

background_image = PhotoImage(file="Background.gif")

background = Label(root, image=background_image, bd=0)
background.pack()

root.mainloop()

Not sure if there is a way of doing this in tkinter? Or if perhaps I would write my own function that resizes the image according to the window size, however the image needs to resize relatively smoothly and quickly if the user resizes the window at any point.

不确定在 tkinter 中是否有办法做到这一点?或者,如果我可能会编写自己的函数来根据窗口大小调整图像大小,但是如果用户在任何时候调整窗口大小,图像需要相对平滑和快速地调整大小。

采纳答案by Marcin

This is example application that uses Pillow to resize image on the Label as the label changes size:

这是示例应用程序,它使用 Pillow 在标签更改大小时调整标签上的图像大小:

from tkinter import *

from PIL import Image, ImageTk

root = Tk()
root.title("Title")
root.geometry("600x600")
root.configure(background="black")



class Example(Frame):
    def __init__(self, master, *pargs):
        Frame.__init__(self, master, *pargs)



        self.image = Image.open("./resource/Background.gif")
        self.img_copy= self.image.copy()


        self.background_image = ImageTk.PhotoImage(self.image)

        self.background = Label(self, image=self.background_image)
        self.background.pack(fill=BOTH, expand=YES)
        self.background.bind('<Configure>', self._resize_image)

    def _resize_image(self,event):

        new_width = event.width
        new_height = event.height

        self.image = self.img_copy.resize((new_width, new_height))

        self.background_image = ImageTk.PhotoImage(self.image)
        self.background.configure(image =  self.background_image)



e = Example(root)
e.pack(fill=BOTH, expand=YES)


root.mainloop()

This is how it works using Lennaimage as example:

这是使用Lenna图像作为示例的工作方式:

enter image description here

在此处输入图片说明

回答by bodger and scraper

I have modified the above code so it is not in a class

我已经修改了上面的代码,所以它不在一个类中

#!/usr/bin/python3.5

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

root = Tk()
root.title("Title")
root.geometry('600x600')

def resize_image(event):
    new_width = event.width
    new_height = event.height
    image = copy_of_image.resize((new_width, new_height))
    photo = ImageTk.PhotoImage(image)
    label.config(image = photo)
    label.image = photo #avoid garbage collection

image = Image.open('image.gif')
copy_of_image = image.copy()
photo = ImageTk.PhotoImage(image)
label = ttk.Label(root, image = photo)
label.bind('<Configure>', resize_image)
label.pack(fill=BOTH, expand = YES)

root.mainloop()

回答by Ujjwal Mohanty

Just sugesting a slight change in the answer. Using self.master.winfo_width(),self.master.winfo_height() instead of 'event' makes he adjustment to size much quicker.

只是建议答案略有变化。使用 self.master.winfo_width(),self.master.winfo_height() 而不是 'event' 可以让他更快地调整尺寸。

import tkinter as tk
from PIL import Image, ImageTk
class Layout:
     def __init__(self,master):
       self.master = master
       self.rootgeometry()
       self.canvas = tk.Canvas(self.master)
       self.canvas.pack()
       self.background_image = Image.open('image_file.PNG') 
       self.image_copy = self.background_image.copy()
       self.background = ImageTk.PhotoImage(self.background_image)
       self.loadbackground()

    def loadbackground(self):
       self.label = tk.Label(self.canvas, image = self.background)
       self.label.bind('<Configure>',self.resizeimage)
       self.label.pack(fill='both', expand='yes')


   def rootgeometry(self):
       x=int(self.master.winfo_screenwidth()*0.7)
       y=int(self.master.winfo_screenheight()*0.7)
       z = str(x) +'x'+str(y)
       self.master.geometry(z)

  def resizeimage(self,event):
       image = self.image_copy.resize((self.master.winfo_width(),self.master.winfo_height()))
       self.image1 = ImageTk.PhotoImage(image)
       self.label.config(image = self.image1)

root = tk.Tk()
a = Styling.Layout(root)
root.mainloop()