Python Tkinter循环更改Enter和Leave上的按钮颜色(Python 3.4,Windows 10)



我正在使用Tkinter的"place"函数创建一些按钮。我想让它们在用户悬停在上面时显示为灰色,然后在光标离开时返回黑色。我可以通过显式绑定它们来实现这一点,但我希望通过循环动态绑定它们。我试图创建的循环位于代码的底部,但它不起作用。

如果你想看看我在说什么,这段代码将在python中运行。

如何创建一个动态循环来执行此操作?

from tkinter import *
FONT_SIZE = 14  # Change this to change all font sizes in the program
root = Tk()
root.resizable(width=TRUE, height=TRUE)
root.geometry("800x600")
root.config(background="black")
# Labels
newGameButton = Label(root)
loadGameButton = Label(root)
optionsButton = Label(root)
exitButton = Label(root)
Labels = [newGameButton, loadGameButton, optionsButton, exitButton]
#Changes the background of buttons when you hover over them
def changeBGEnter(widget):
    widget.config(background="gray")
#Changes the background of buttons when you stop hovering them
def changeBGLeave(widget):
    widget.config(background="black")
# Explicit bindings, ugly
newGameButton.bind("<Enter>", lambda x: changeBGEnter(newGameButton))
newGameButton.bind("<Leave>", lambda x: changeBGLeave(newGameButton))
loadGameButton.bind("<Enter>", lambda x: changeBGEnter(loadGameButton))
loadGameButton.bind("<Leave>", lambda x: changeBGLeave(loadGameButton))
optionsButton.bind("<Enter>", lambda x: changeBGEnter(optionsButton))
optionsButton.bind("<Leave>", lambda x: changeBGLeave(optionsButton))
exitButton.bind("<Enter>", lambda x: changeBGEnter(exitButton))
exitButton.bind("<Leave>", lambda x: changeBGLeave(exitButton))
# New Game Button
newGameButton.config(
    anchor=CENTER,  # Where to anchor the text in the widget
    background="black",
    foreground="white",
    font=("default", FONT_SIZE),
    text="NewGame",
)
newGameButton.place(
    relwidth=0.6,
    relheight=0.1,
    relx=0.2,
    rely=0.3
)
# Load Game Button
loadGameButton.config(
    anchor=CENTER,
    background="black",
    foreground="white",
    font=("default", FONT_SIZE),
    text="Stats",
)
loadGameButton.place(
    relwidth=0.6,
    relheight=0.1,
    relx=0.2,
    rely=0.4
)
# Options Button
optionsButton.config(
    anchor=CENTER,
    background="black",
    foreground="white",
    font=("default", FONT_SIZE),
    text="Output",
)
optionsButton.place(
    relwidth=0.6,
    relheight=0.1,
    relx=0.2,
    rely=0.5
)
# Exit Button
exitButton.config(
    anchor=CENTER,
    background="black",
    foreground="white",
    font=("default", FONT_SIZE),
    text="Exit",
)
exitButton.place(
    relwidth=0.6,
    relheight=0.1,
    relx=0.2,
    rely=0.6
)
#Code I want that doesn't work:
#Get rid of explicit bindings above to test the code below
"""
for x in Labels:
    x.bind("<Enter>", lambda x: changeBGEnter(x))
    x.bind("<Leave>", lambda x: changeBGLeave(x))
"""
root.mainloop()
  1. bind发送event data作为lambda中的第一个参数,因此xevent data,而不是标签。

  2. (在for循环中)lambda不会将值从lab复制到changeBGEnter(lab)(但使用lab作为参考,所有changeBGEnter都得到相同的最后一个标签),因此您必须使用label=lab 复制它

for lab in Labels:
    lab.bind("<Enter>", lambda event, label=lab: changeBGEnter(label))
    lab.bind("<Leave>", lambda event, label=lab: changeBGLeave(label))

-

(顺便说一句:你可以创建自己的小部件来简化它)


编辑:自己的小部件MyButton,带有绑定的<Enter><Leave>

from tkinter import *

class MyButton(Label):
    def __init__(self, *args, **kwargs):
        Label.__init__(self, *args, **kwargs)
        self.bind("<Enter>", self.changeBGEnter)
        self.bind("<Leave>", self.changeBGLeave)
    def changeBGEnter(self, event):
        self.config(background="gray")
    def changeBGLeave(self, event):
        self.config(background="black")

FONT_SIZE = 14  # Change this to change all font sizes in the program
root = Tk()
root.resizable(width=TRUE, height=TRUE)
root.geometry("800x600")
root.config(background="black")
# Labels
newGameButton = MyButton(root)
loadGameButton = MyButton(root)
optionsButton = MyButton(root)
exitButton = MyButton(root)
Labels = [newGameButton, loadGameButton, optionsButton, exitButton]
# New Game Button
newGameButton.config(
    anchor=CENTER,  # Where to anchor the text in the widget
    background="black",
    foreground="white",
    font=("default", FONT_SIZE),
    text="NewGame",
)
newGameButton.place(
    relwidth=0.6,
    relheight=0.1,
    relx=0.2,
    rely=0.3
)
# Load Game Button
loadGameButton.config(
    anchor=CENTER,
    background="black",
    foreground="white",
    font=("default", FONT_SIZE),
    text="Stats",
)
loadGameButton.place(
    relwidth=0.6,
    relheight=0.1,
    relx=0.2,
    rely=0.4
)
# Options Button
optionsButton.config(
    anchor=CENTER,
    background="black",
    foreground="white",
    font=("default", FONT_SIZE),
    text="Output",
)
optionsButton.place(
    relwidth=0.6,
    relheight=0.1,
    relx=0.2,
    rely=0.5
)
# Exit Button
exitButton.config(
    anchor=CENTER,
    background="black",
    foreground="white",
    font=("default", FONT_SIZE),
    text="Exit",
)
exitButton.place(
    relwidth=0.6,
    relheight=0.1,
    relx=0.2,
    rely=0.6
)
root.mainloop()

编辑:但您可以使用tkinter.Button来获得相同的结果,而无需自己的小部件或循环。

您可以使用command=为按钮点击分配功能。

exitButton = Button(root)
def command_exit():
    print "exit"
    root.destroy()
exitButton.config(
    anchor=CENTER,
    font=("default", FONT_SIZE),
    text="Exit",
    # Leave colors
    background="black",
    foreground="white",
    # without border    
    borderwidth=0,
    highlightthickness=0,
    # Enter colors
    activebackground="grey",
    activeforeground="white",
    # run on click
    command=command_exit
)

最新更新