在同一窗口上用OOP创建tkinter按钮:issue



我是Python的初学者。我创建了一个带有漂亮按钮的GUI。为了做到这一点,我更改了图像:当鼠标悬停在按钮上时,以及当鼠标离开按钮时。我用这个非常丑陋的代码做到了这一点,但它有效:

from tkinter import *
from PIL import Image, ImageTk
root = Tk()
root.title("My first Python GUI")
root.geometry("1130x800")
canvas = Canvas(root, bg="#a9dfbf")
canvas.pack(fill=BOTH, expand=True)
button_1_onHover = Image.open("Buttons/button1_hover.png")
button_1_onLeave = Image.open("Buttons/button1_leave.png")
button_2_onHover = Image.open("Buttons/button2_hover.png")
button_2_onLeave = Image.open("Buttons/button2_leave.png")
root.button_1_onLeave = ImageTk.PhotoImage(button_1_onLeave)
root.button_1_onHover = ImageTk.PhotoImage(button_1_onHover)
root.button_2_onLeave = ImageTk.PhotoImage(button_2_onLeave)
root.button_2_onHover = ImageTk.PhotoImage(button_2_onHover)
def on_enter(event):
button1.config(image=root.button_1_onHover)
def on_leave(leave):
button1.config(image=root.button_1_onLeave)

def on_enter2(event):
button2.config(image=root.button_2_onHover)
def on_leave2(leave):
button2.config(image=root.button_2_onLeave)

button1 = Button(root, image=root.button_1_onLeave, bg="#a9dfbf", width=400, height=150, bd=0, relief="sunken", activebackground="#a9dfbf")
button2 = Button(root, image=root.button_2_onLeave, bg="#a9dfbf", width=400, height=150, bd=0, relief="sunken", activebackground="#a9dfbf")
canvas.create_window(300, 150, window=button1)
canvas.create_window(300, 350, window=button2)
button1.bind("<Enter>", on_enter)
button1.bind("<Leave>", on_leave)
button2.bind("<Enter>", on_enter2)
button2.bind("<Leave>", on_leave2)
root.mainloop()

这是视觉结果:丑陋代码的视觉结果(它工作(

但是。。。问题是,制作一个按钮需要15行代码。如果我想创建10个按钮,它会变得令人难以置信的重复和不愉快。作为一个初学者,我听说了面向对象编程,所以我把我的代码变成了一个类,我称之为NewButton:

from tkinter import *
from PIL import Image, ImageTk

class NewButton:
def __init__(self, imageHover, imageLeave, width, height, hposition, vposition):

self.root = Tk()
self.root.title("My first Python GUI")
self.root.geometry("1130x800")

canvas = Canvas(self.root, bg="#a9dfbf")
canvas.pack(fill=BOTH, expand=True)

self.width = width
self.height = height
self.hposition = hposition
self.vposition = vposition

self.imageHover = Image.open(f"Buttons/{imageHover}.png")
self.imageLeave = Image.open(f"Buttons/{imageLeave}.png")
self.root.imageLeave = ImageTk.PhotoImage(self.imageLeave)
self.root.imageHover = ImageTk.PhotoImage(self.imageHover)

self.button = Button(self.root, image=self.root.imageLeave, bg="#a9dfbf", width=self.width, height=self.height, bd=0, relief="sunken", activebackground="#a9dfbf")
canvas.create_window(self.hposition, self.vposition, window=self.button)

def on_enter(event):
self.button.config(image=self.root.imageHover)
def on_leave(leave):
self.button.config(image=self.root.imageLeave)
self.button.bind("<Enter>", on_enter)
self.button.bind("<Leave>", on_leave)
self.root.mainloop()

NewButton("button1_hover","button1_leave",400,150,300,150)
NewButton("button2_hover","button2_leave",400,150,300,350)

在我类的构造函数中,我定义了悬停时使用的图像、离开时使用的图片、按钮的宽度、高度以及按钮的位置(水平位置和垂直位置(。仍然在构造函数中,我放置了2个函数,它们根据进入/离开状态更改图像。

然后我将我的按钮创建为NewButton对象,并给出按钮的特性。当我运行代码时,python会为我创建按钮,但在不同的窗口中。这是视觉结果:POO代码的结果(不工作(

我想要的是把我创建的所有按钮都放在同一个窗口上,而这不是我的代码所能得到的。你能告诉我怎么了吗?谢谢你(也为我的法式英语感到抱歉!(

我尝试的acw1668解决方案(不起作用(:他的建议:";您需要在类外部创建根和画布,并将画布传递给类实例"我所做的:

from tkinter import *
from PIL import Image, ImageTk

root = Tk()
root.title("My first Python GUI")
root.geometry("1130x800")
canvas = Canvas(root, bg="#a9dfbf")
canvas.pack(fill=BOTH, expand=True)

class NewButton:
def __init__(self, canvas, imageHover, imageLeave, width, height, hposition, vposition):
self.canvas = canvas
self.width = width
self.height = height
self.hposition = hposition
self.vposition = vposition

self.imageHover = Image.open(f"Buttons/{imageHover}.png")
self.imageLeave = Image.open(f"Buttons/{imageLeave}.png")
self.canvas.imageLeave = ImageTk.PhotoImage(self.imageLeave)
self.canvas.imageHover = ImageTk.PhotoImage(self.imageHover)

self.button = Button(self.canvas, image=self.canvas.imageLeave, bg="#a9dfbf", width=self.width, height=self.height, bd=0, relief="sunken", activebackground="#a9dfbf")
canvas.create_window(self.hposition, self.vposition, window=self.button)

def on_enter(event):
self.button.config(image=self.canvas.imageHover)
def on_leave(leave):
self.button.config(image=self.canvas.imageLeave)
self.button.bind("<Enter>", on_enter)
self.button.bind("<Leave>", on_leave)
self.canvas.mainloop()

NewButton(canvas,"button1_hover","button1_leave",400,150,300,150)
NewButton(canvas,"button2_hover","button2_leave",400,150,300,350)

您需要在类外创建rootcanvas,然后将canvas传递给类:

from tkinter import *
from PIL import Image, ImageTk

class NewButton:
def __init__(self, canvas, imageHover, imageLeave, width, height, hposition, vposition):
self.canvas = canvas
self.width = width
self.height = height
self.hposition = hposition
self.vposition = vposition
imageHover = Image.open(f"Buttons/{imageHover}.png")
imageLeave = Image.open(f"Buttons/{imageLeave}.png")
self.imageLeave = ImageTk.PhotoImage(imageLeave)
self.imageHover = ImageTk.PhotoImage(imageHover)
self.button = Button(canvas, image=self.imageLeave, bg="#a9dfbf", width=self.width, height=self.height, bd=0, relief="sunken", activebackground="#a9dfbf")
self.button.bind("<Enter>", self.on_enter)
self.button.bind("<Leave>", self.on_leave)
self.item_id = canvas.create_window(self.hposition, self.vposition, window=self.button)
def on_enter(self, event):
self.button.config(image=self.imageHover)
def on_leave(self, event):
self.button.config(image=self.imageLeave)

root = Tk()
root.title("My first Python GUI")
root.geometry("1130x800")
canvas = Canvas(root, bg="#a9dfbf")
canvas.pack(fill=BOTH, expand=True)
NewButton(canvas,"button1_hover","button1_leave",400,150,300,150)
NewButton(canvas,"button2_hover","button2_leave",400,150,300,350)
root.mainloop()

最新更新