python - Frame中的tkinter背景图像
问题描述
我想将背景图像放在框架中,这是我试图运行但没有成功的代码。
import tkinter as tk
from tkinter import *
root = tk.Tk()
F1 = Frame(root)
F1.grid(row=0)
photo = PhotoImage(file="sfondo.png")
label = Label(F1, image=photo)
label.image = photo
label.place(x=0, y=0)
b = tk.Button(label, text="Start")
b.grid(row=8, column=8)
root.mainloop()
如果我这样运行代码,则只显示左上角的一点(即使我在其中放置了标签,框架也没有任何内容)。如果我将标签父级替换为root
,它会显示带有图像的一小部分的按钮作为背景(仅按钮的周边被着色为几个像素)。但是我想要的是在框架中完整显示的背景图像,我可以在其中放置我想要的小部件。
我尝试使用 place 方法作为 this 和 PIL 模块
import tkinter as tk
from tkinter import *
from PIL import Image, ImageTk
root = tk.Tk()
F1 = Frame(root)
F1.grid(row=0)
image = Image.open("sfondo.png")
render = ImageTk.PhotoImage(image)
img = tk.Label(F1, image=render)
img.image = render
img.place(x=0, y=40)
b = tk.Button(img, text="Start")
b.grid(row=8, column=8)
root.mainloop()
在这里或多或少我遇到了同样的问题,如果我将标签的父级设置为root
,则按钮显示为带有彩色的周边。如果我将父级设置为F1
没有任何反应,并且在这两种情况下,如果我将父级设置为root
并删除按钮,则图像将完全显示。但我想要的是图像完全显示在框架中,然后在背景图像上显示小部件。
解决方案
您可以将图像放在 a上Canvas
,然后Button
通过将其放在可以容纳任何 Tkinter 小部件的Canvas 窗口对象中来放置 a 。
可以以类似的方式添加其他小部件,每个小部件都在其自己的Canvas
窗口对象中(因为它们每个只能容纳一个小部件)。Frame
您可以通过在窗口中放置一个小部件Canvas
,然后将其他小部件放入其中来解决该限制。
这是一个显示如何显示单个的示例Button
:
from PIL import Image, ImageTk
import tkinter as tk
IMAGE_PATH = 'sfondo.png'
WIDTH, HEIGTH = 200, 200
root = tk.Tk()
root.geometry('{}x{}'.format(WIDTH, HEIGHT))
canvas = tk.Canvas(root, width=WIDTH, height=HEIGTH)
canvas.pack()
img = ImageTk.PhotoImage(Image.open(IMAGE_PATH).resize((WIDTH, HEIGTH), Image.ANTIALIAS))
canvas.background = img # Keep a reference in case this code is put in a function.
bg = canvas.create_image(0, 0, anchor=tk.NW, image=img)
# Put a tkinter widget on the canvas.
button = tk.Button(root, text="Start")
button_window = canvas.create_window(10, 10, anchor=tk.NW, window=button)
root.mainloop()
截屏:
编辑
虽然我不知道用 aFrame
代替的方法Canvas
,但您可以派生自己的Frame
子类以更轻松地添加多个小部件。这就是我的意思:
from PIL import Image, ImageTk
import tkinter as tk
class BkgrFrame(tk.Frame):
def __init__(self, parent, file_path, width, height):
super(BkgrFrame, self).__init__(parent, borderwidth=0, highlightthickness=0)
self.canvas = tk.Canvas(self, width=width, height=height)
self.canvas.pack()
pil_img = Image.open(file_path)
self.img = ImageTk.PhotoImage(pil_img.resize((width, height), Image.ANTIALIAS))
self.bg = self.canvas.create_image(0, 0, anchor=tk.NW, image=self.img)
def add(self, widget, x, y):
canvas_window = self.canvas.create_window(x, y, anchor=tk.NW, window=widget)
return widget
if __name__ == '__main__':
IMAGE_PATH = 'sfondo.png'
WIDTH, HEIGTH = 350, 200
root = tk.Tk()
root.geometry('{}x{}'.format(WIDTH, HEIGTH))
bkrgframe = BkgrFrame(root, IMAGE_PATH, WIDTH, HEIGTH)
bkrgframe.pack()
# Put some tkinter widgets in the BkgrFrame.
button1 = bkrgframe.add(tk.Button(root, text="Start"), 10, 10)
button2 = bkrgframe.add(tk.Button(root, text="Continue"), 50, 10)
root.mainloop()
结果:
更新
我最近突然意识到,实际上有一种比创建自定义Frame
子类更简单的方法,如上面我之前的编辑所示。诀窍是在父对象的中心添加place()
一个图像——然后你可以像往常一样自由地使用其他几何管理器——如下面的示例代码所示。它不仅不那么复杂,而且与需要调用非标准方法(例如.Label
Frame
pack()
grid()
add()
from PIL import Image, ImageTk
import tkinter as tk
IMAGE_PATH = 'sfondo.png'
WIDTH, HEIGHT = 250, 150
root = tk.Tk()
root.geometry('{}x{}'.format(WIDTH, HEIGHT))
# Display image on a Label widget.
img = ImageTk.PhotoImage(Image.open(IMAGE_PATH).resize((WIDTH, HEIGHT), Image.ANTIALIAS))
lbl = tk.Label(root, image=img)
lbl.img = img # Keep a reference in case this code put is in a function.
lbl.place(relx=0.5, rely=0.5, anchor='center') # Place label in center of parent.
# Add other tkinter widgets.
button = tk.Button(root, text="Start")
button.grid(row=0, column=0)
button = tk.Button(root, text="Continue")
button.grid(row=0, column=1, padx=10)
root.mainloop()
结果#2
PS你可以从这里sfondo.png
下载背景图片的副本。
推荐阅读
- android - 嵌套布局?
- laravel - 我无法使用 laravel 和 vue js 打印图像
- c# - C# - 创建一个数字生成器,其中包含在文本框中写入的特定数字
- unity3d - Unity 5.3.8 Animator - 故障?
- python - 无法运行 anaconda
- docker - docker内存自动升级
- r - 在不使用 XLConnect 的情况下将数据写入 R 中的 xlsx 模板
- c# - 在 linq 查询中使用字典
- r - 无法转换标题或转换时间取决于在新版本的 gganimate 中使用 transition_states 或 transition_times
- java - 从 android 将媒体上传到 S3 存储桶时出错