【问题标题】:Tkinter resize background image to window sizeTkinter 将背景图像调整为窗口大小
【发布时间】:2014-07-26 12:00:13
【问题描述】:

尝试为我的 tkinter 窗口设置背景。我有一个方形背景图像,边缘逐渐变黑,然后主窗口有黑色背景。图像被放置在背景上,如果窗口比它高,图像在黑色背景的中间居中,看起来非常漂亮。

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

所以说背景图片是600x600:

  • 在800x400 窗口中,图像不会调整大小,而是垂直居中。
  • 在500x400 窗口中,图像调整为500x500,并且仍然垂直居中。
  • 在400x900 窗口中,图像不会调整大小,而是水平居中。

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

目前我拥有的是:

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()

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

【问题讨论】:

  • 使用pillow 调整图像大小。

标签: python python-3.x tkinter


【解决方案1】:

这是一个示例应用程序,它使用 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()

以Lenna 图片为例:

【解决方案2】:

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

#!/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()

【讨论】:

【解决方案3】:

只是暗示答案略有变化。使用 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()

【讨论】:

    【解决方案4】:

    我创建了一个函数,用于在取消之后使用 et 之后的方法调用一次调整大小

        def on_resize(self, evt):
            
            if self.inter == 0:
                self.inter = 1
                self.minuteur = self.fenetrePrincipale.after(100, self.endResize)
            else:
                self.minuteur = self.fenetrePrincipale.after_cancel(self.minuteur)
                self.minuteur = self.fenetrePrincipale.after(100, self.endResize)
                
        def endResize(self):
            self.inter = 0
            self.fenetrePrincipale.background = self.fenetrePrincipale.background.resize((self.fenetrePrincipale.winfo_width(), self.fenetrePrincipale.winfo_height()))
            self.pixi = ImageTk.PhotoImage(self.fenetrePrincipale.background)
            self.canvas.configure(width=self.fenetrePrincipale.winfo_width(), height=self.fenetrePrincipale.winfo_height())
            self.canvas.create_image(0, 0, anchor=NW, image=self.pixi)
    
    

    原理如下, after 定义了一个定时器和一个最后要调用的函数,after_cancel 清理定时器,所以函数的每次迭代都会清理定时器并启动它,在最后一次 resize 迭代时,定时器仍然被触发。 有关取消和计时器的更多信息: after detailled

    【讨论】:

      猜你喜欢
      • 2023-02-11
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 2014-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-05
      相关资源
      最近更新 更多