在同一窗口上使用 OOP 创建 tkinter 按钮:问题
我是 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)
在我的类的构造函数中,我定义了悬停时使用的图像、离开时使用的图像、按钮的宽度。按钮、其高度以及该按钮的位置(水平位置和垂直位置)。 仍在构造函数中,我放置了两个函数,它们根据进入/离开状态更改图像。
然后我将按钮创建为 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)
I am a beginner in Python. I created a GUI with nice buttons. To do this I did a change of images: when the mouse hovers the button and when the mouse leaves the button. I did this with this pretty ugly code, but it works:
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()
This is the visual result:
visual result of the ugly code (it work)
BUT...
The problem is that to make a single button, it takes 15 lines of code.
If I want to create 10 buttons, it becomes incredibly repetitive and unpleasant.
Being a beginner, I heard about object-oriented programming, and so I turned my code into a class that I called 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)
In the constructor of my class, I define the image used on hover, the image used on leave, the width of the button, its height, as well as the position of this button (horizontal position and vertical position).
Still in the constructor, I placed my 2 functions which change the image according to the enter/leave state.
Then I create my buttons as NewButton objects and give the characteristics of the button.
When I run my code, python creates the buttons for me, but in a different window.
This is the visual result:
result with POO code (not working)
What I want is to put all the buttons that I create on the same window, and that's not what I get with my code.
Can you tell me what's wrong?
Thank you (and sorry for my frenglish!)
SOLUTION by acw1668 that i try (it doesn't work):
His suggestion: "You need to create root and canvas outside the class and pass canvas to the class instance instead."
what I have done:
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您需要在类外部创建
root
和canvas
,然后将canvas
传递给类:You need to create
root
andcanvas
outside the class and then passcanvas
to the class: