如何使用 OOP 概念在 Tkinter 中添加背景图像?
How to add background image in Tkinter using OOP concept?
我是面向对象 python 编程的新手。目前我正在使用 Python 3. 我想创建一个有多个页面的应用程序。我可以在页面之间导航,但发现很难在后台添加图像。
请注意,我不想知道如何在 tkinter 中设置背景图片,因为我已经可以根据以下代码做到这一点。
bg = PhotoImage(file="images\bg.png")
label_bgImage = Label(master, image=bg)
label_bgImage.place(x=0, y=0)
我想知道如何在将每个 window 定义为 class 时向页面添加背景图像。我把插入背景图片的代码放在了class ABCApp
的__init__()
方法中。当我尝试将用于添加背景图像的代码插入现有代码时,它停止显示标签和按钮,现在只显示 window.
以下代码是我尝试添加图像作为背景。
import tkinter as tk
from tkinter import ttk
from tkinter import *
class ABCApp(tk.Tk):
def __init__(self,*args,**kwargs):
tk.Tk.__init__(self,*args,**kwargs)
self.geometry("1500x750")
main_frame = tk.Frame(self)
main_frame.pack(side = 'top',fill = 'both',expand ='True')
main_frame.grid_rowconfigure(0,weight=1)
main_frame.grid_columnconfigure(0,weight=1)
bg = PhotoImage(file="images\bg.png")
label_bgImage = Label(self, image=bg)
label_bgImage.place(x=0, y=0)
self.frames = {}
for F in (HomePage,PageOne,PageTwo):
frame = F(main_frame, self)
self.frames[F] = frame
frame.grid(row=0,column=0,sticky='nsew')
self.show_frame(HomePage)
def show_frame(self,container):
frame = self.frames[container]
frame.tkraise()
class HomePage(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
label = ttk.Label(self,text='Home Page',font =("Helvetica",20))
label.pack(padx=10,pady=10)
button1 = ttk.Button(self,text = "Page 1",command = lambda: controller.show_frame(PageOne))
button1.pack()
button6 = ttk.Button(self, text="Page 2", command=lambda: controller.show_frame(PageTwo))
button6.pack()
class PageOne(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self, parent)
label1 = ttk.Label(self, text='Page 1', font=("Helvetica", 20))
label1.pack(padx=10, pady=10)
button2 = ttk.Button(self, text="Back", command=lambda: controller.show_frame(HomePage))
button2.pack()
button5 = ttk.Button(self, text="Page 2", command=lambda: controller.show_frame(PageTwo))
button5.pack()
class PageTwo(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self, parent)
label2 = ttk.Label(self, text='Page 2', font=("Helvetica", 20))
label2.pack(padx=10, pady=10)
button3 = ttk.Button(self, text="Back", command=lambda: controller.show_frame(HomePage))
button3.pack()
button4 = ttk.Button(self, text="Page 1", command=lambda: controller.show_frame(PageOne))
button4.pack()
app = ABCApp()
app.mainloop()
我希望将相同或不同的图像显示为每个页面的背景。不管怎样我都很满意
由于背景图像在所有 Page
classes 上都是相同的,因此一种面向对象的方法是定义一个 base class 上面有背景图片,然后从中导出所有具体的 Page
classes 而不是普通的 tk.Frame
。之后,每个 subclass 都需要调用其基础 class' __init__()
方法,然后再添加它独有的任何小部件。在下面的代码中,这个新基 class 就是名为 BasePage
.
的基
为避免为每个 BasePage
子 class 实例加载图像文件的单独副本,它只完成一次并保存为 ABCApp
[=39= 的属性](这是传递给每个 BasePage
subclass 的构造函数的 controller
参数)。因为每个页面 class 在显示时会完全覆盖所有其他页面,所以每个页面都需要创建自己的 Label
并在其上放置背景图片。
下面显示了我的意思。 (注意我使代码比你问题中的更PEP 8 - Style Guide for Python Code兼容)。
import tkinter as tk
from tkinter.constants import *
from tkinter import ttk
class ABCApp(tk.Tk):
BKGR_IMAGE_PATH = '8-ball.png'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.geometry("1500x750")
main_frame = tk.Frame(self)
main_frame.pack(side='top', fill='both', expand='True')
main_frame.grid_rowconfigure(0, weight=1)
main_frame.grid_columnconfigure(0, weight=1)
self.bkgr_image = tk.PhotoImage(file=self.BKGR_IMAGE_PATH)
self.frames = {}
for F in (HomePage, PageOne, PageTwo):
frame = F(main_frame, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky='nsew')
self.show_frame(HomePage)
def show_frame(self,container):
frame = self.frames[container]
frame.tkraise()
class BasePage(tk.Frame):
def __init__(self, parent, controller):
super().__init__(parent)
label_bkgr = tk.Label(self, image=controller.bkgr_image)
label_bkgr.place(relx=0.5, rely=0.5, anchor=CENTER) # Center label w/image.
class HomePage(BasePage):
def __init__(self, parent, controller):
super().__init__(parent, controller)
label = ttk.Label(self, text='Home Page', font =("Helvetica",20))
label.pack(padx=10, pady=10)
button1 = ttk.Button(self, text="Page 1",
command=lambda: controller.show_frame(PageOne))
button1.pack()
button6 = ttk.Button(self, text="Page 2",
command=lambda: controller.show_frame(PageTwo))
button6.pack()
class PageOne(BasePage):
def __init__(self,parent,controller):
super().__init__(parent, controller)
label1 = ttk.Label(self, text='Page 1', font=("Helvetica", 20))
label1.pack(padx=10, pady=10)
button2 = ttk.Button(self, text="Back",
command=lambda: controller.show_frame(HomePage))
button2.pack()
button5 = ttk.Button(self, text="Page 2",
command=lambda: controller.show_frame(PageTwo))
button5.pack()
class PageTwo(BasePage):
def __init__(self, parent, controller):
super().__init__(parent, controller)
label2 = ttk.Label(self, text='Page 2', font=("Helvetica", 20))
label2.pack(padx=10, pady=10)
button3 = ttk.Button(self, text="Back",
command=lambda: controller.show_frame(HomePage))
button3.pack()
button4 = ttk.Button(self, text="Page 1",
command=lambda: controller.show_frame(PageOne))
button4.pack()
app = ABCApp()
app.mainloop()
另请注意,如果您希望每个 Page
class 具有不同的背景图片,您可以做一些不同的事情 - 即每个页面 将 负责加载自己的图像。为此,对 BasePage
构造函数的调用需要传递要使用的图像文件的名称(作为 super().__init__()
语句中的附加参数)。
我是面向对象 python 编程的新手。目前我正在使用 Python 3. 我想创建一个有多个页面的应用程序。我可以在页面之间导航,但发现很难在后台添加图像。
请注意,我不想知道如何在 tkinter 中设置背景图片,因为我已经可以根据以下代码做到这一点。
bg = PhotoImage(file="images\bg.png")
label_bgImage = Label(master, image=bg)
label_bgImage.place(x=0, y=0)
我想知道如何在将每个 window 定义为 class 时向页面添加背景图像。我把插入背景图片的代码放在了class ABCApp
的__init__()
方法中。当我尝试将用于添加背景图像的代码插入现有代码时,它停止显示标签和按钮,现在只显示 window.
以下代码是我尝试添加图像作为背景。
import tkinter as tk
from tkinter import ttk
from tkinter import *
class ABCApp(tk.Tk):
def __init__(self,*args,**kwargs):
tk.Tk.__init__(self,*args,**kwargs)
self.geometry("1500x750")
main_frame = tk.Frame(self)
main_frame.pack(side = 'top',fill = 'both',expand ='True')
main_frame.grid_rowconfigure(0,weight=1)
main_frame.grid_columnconfigure(0,weight=1)
bg = PhotoImage(file="images\bg.png")
label_bgImage = Label(self, image=bg)
label_bgImage.place(x=0, y=0)
self.frames = {}
for F in (HomePage,PageOne,PageTwo):
frame = F(main_frame, self)
self.frames[F] = frame
frame.grid(row=0,column=0,sticky='nsew')
self.show_frame(HomePage)
def show_frame(self,container):
frame = self.frames[container]
frame.tkraise()
class HomePage(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
label = ttk.Label(self,text='Home Page',font =("Helvetica",20))
label.pack(padx=10,pady=10)
button1 = ttk.Button(self,text = "Page 1",command = lambda: controller.show_frame(PageOne))
button1.pack()
button6 = ttk.Button(self, text="Page 2", command=lambda: controller.show_frame(PageTwo))
button6.pack()
class PageOne(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self, parent)
label1 = ttk.Label(self, text='Page 1', font=("Helvetica", 20))
label1.pack(padx=10, pady=10)
button2 = ttk.Button(self, text="Back", command=lambda: controller.show_frame(HomePage))
button2.pack()
button5 = ttk.Button(self, text="Page 2", command=lambda: controller.show_frame(PageTwo))
button5.pack()
class PageTwo(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self, parent)
label2 = ttk.Label(self, text='Page 2', font=("Helvetica", 20))
label2.pack(padx=10, pady=10)
button3 = ttk.Button(self, text="Back", command=lambda: controller.show_frame(HomePage))
button3.pack()
button4 = ttk.Button(self, text="Page 1", command=lambda: controller.show_frame(PageOne))
button4.pack()
app = ABCApp()
app.mainloop()
我希望将相同或不同的图像显示为每个页面的背景。不管怎样我都很满意
由于背景图像在所有 Page
classes 上都是相同的,因此一种面向对象的方法是定义一个 base class 上面有背景图片,然后从中导出所有具体的 Page
classes 而不是普通的 tk.Frame
。之后,每个 subclass 都需要调用其基础 class' __init__()
方法,然后再添加它独有的任何小部件。在下面的代码中,这个新基 class 就是名为 BasePage
.
为避免为每个 BasePage
子 class 实例加载图像文件的单独副本,它只完成一次并保存为 ABCApp
[=39= 的属性](这是传递给每个 BasePage
subclass 的构造函数的 controller
参数)。因为每个页面 class 在显示时会完全覆盖所有其他页面,所以每个页面都需要创建自己的 Label
并在其上放置背景图片。
下面显示了我的意思。 (注意我使代码比你问题中的更PEP 8 - Style Guide for Python Code兼容)。
import tkinter as tk
from tkinter.constants import *
from tkinter import ttk
class ABCApp(tk.Tk):
BKGR_IMAGE_PATH = '8-ball.png'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.geometry("1500x750")
main_frame = tk.Frame(self)
main_frame.pack(side='top', fill='both', expand='True')
main_frame.grid_rowconfigure(0, weight=1)
main_frame.grid_columnconfigure(0, weight=1)
self.bkgr_image = tk.PhotoImage(file=self.BKGR_IMAGE_PATH)
self.frames = {}
for F in (HomePage, PageOne, PageTwo):
frame = F(main_frame, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky='nsew')
self.show_frame(HomePage)
def show_frame(self,container):
frame = self.frames[container]
frame.tkraise()
class BasePage(tk.Frame):
def __init__(self, parent, controller):
super().__init__(parent)
label_bkgr = tk.Label(self, image=controller.bkgr_image)
label_bkgr.place(relx=0.5, rely=0.5, anchor=CENTER) # Center label w/image.
class HomePage(BasePage):
def __init__(self, parent, controller):
super().__init__(parent, controller)
label = ttk.Label(self, text='Home Page', font =("Helvetica",20))
label.pack(padx=10, pady=10)
button1 = ttk.Button(self, text="Page 1",
command=lambda: controller.show_frame(PageOne))
button1.pack()
button6 = ttk.Button(self, text="Page 2",
command=lambda: controller.show_frame(PageTwo))
button6.pack()
class PageOne(BasePage):
def __init__(self,parent,controller):
super().__init__(parent, controller)
label1 = ttk.Label(self, text='Page 1', font=("Helvetica", 20))
label1.pack(padx=10, pady=10)
button2 = ttk.Button(self, text="Back",
command=lambda: controller.show_frame(HomePage))
button2.pack()
button5 = ttk.Button(self, text="Page 2",
command=lambda: controller.show_frame(PageTwo))
button5.pack()
class PageTwo(BasePage):
def __init__(self, parent, controller):
super().__init__(parent, controller)
label2 = ttk.Label(self, text='Page 2', font=("Helvetica", 20))
label2.pack(padx=10, pady=10)
button3 = ttk.Button(self, text="Back",
command=lambda: controller.show_frame(HomePage))
button3.pack()
button4 = ttk.Button(self, text="Page 1",
command=lambda: controller.show_frame(PageOne))
button4.pack()
app = ABCApp()
app.mainloop()
另请注意,如果您希望每个 Page
class 具有不同的背景图片,您可以做一些不同的事情 - 即每个页面 将 负责加载自己的图像。为此,对 BasePage
构造函数的调用需要传递要使用的图像文件的名称(作为 super().__init__()
语句中的附加参数)。