切换引用相同功能的相同代码的按钮

时间:2018-10-08 18:50:53

标签: python python-3.x button tkinter togglebutton

我试图编写一个宾果网格程序,并希望减少代码以使其更简单。我目前正在重复此代码:

from tkinter import *
from tkinter import Tk, Button, Label
mycolor = '#FF7F50'
mycolor2 = '#FFFFFF'
mycolor3 = '#BAF0FF'
class Window:

    def __init__(self, master):
        self.master = master
        self.master.title("Bingo")
        self.master.minsize(width=1920, height=1080)
        self.master.config(bg=mycolor3)

        self.A = Button(master, text='1', font=('Helvetica', '23'), height=1, width=20, command=self.toggleA, bg=mycolor2)
        self.A.grid(column=0,row=1)

        self.B = Button(master, text='2', font=('Helvetica', '23'), height=1, width=20, command=self.toggleB, bg=mycolor2)
        self.B.grid(column=0,row=2)

    def toggleA(self):
        self.A.config('bg')
        if self.A.config('bg')[-1] == mycolor2:
            self.A.config(bg=mycolor)
        else:
            self.A.config(bg=mycolor2)
    def toggleB(self):
        self.B.config('bg')
        if self.B.config('bg')[-1] == mycolor2:
            self.B.config(bg=mycolor)
        else:
            self.B.config(bg=mycolor2)
root = Tk()
my_win = Window(root)
root.mainloop()

并准确地使用此脚本,我必须通过更改变量名称来重复该脚本75次以完成程序,此方法可行,但是我想知道是否有一种方法可以对与每个按钮相对的按钮进行相同的定义为每个按钮定义一个新的切换?切换按钮用于影响按钮的颜色,从而将其从一种颜色切换为另一种颜色,我不确定如何获得所有按钮调用的相同命令来分别影响每个按钮。 谢谢!

3 个答案:

答案 0 :(得分:1)

一种选择是将self.Aself.B等放入列表中(例如self.buttons)。

然后您可以创建toggleA(self),而不用创建toggleB(self)toggle(self,button)等,而是使用其button自变量,而您当前正在使用self.A,{ {1}},等等。

然后在self.B上使用for循环,并在每个循环上调用self.buttons

toggle

答案 1 :(得分:0)

以下是可运行的内容,显示了如何执行我的评论之一中建议的方法:

from tkinter import Tk, Button, Label

MY_COLOR = '#FF7F50'
MY_COLOR2 = '#FFFFFF'
MY_COLOR3 = '#BAF0FF'
NUM_BUTTONS = 3


class Toggler:
    """ Toggles background color of a Button widget when called. """
    def __init__(self, btn, color, color2):
        self.btn = btn
        self.color = color
        self.color2 = color2

    def __call__(self):
        if self.btn.cget('bg') == self.color:
            self.btn.config(bg=self.color2)
        else:
            self.btn.config(bg=self.color)


class Window:
    def __init__(self, master):
        self.master = master
        self.master.title("Bingo")
        self.master.minsize(width=800, height=600)
        self.master.config(bg=MY_COLOR3)

        # Create the buttons.
        self.buttons = []
        self.togglers = []
        for i in range(NUM_BUTTONS):
            btn = Button(master, text='Button %d' % i, font=('Helvetica', '23'),
                         height=1, width=20, bg=MY_COLOR2)
            btn.grid(column=0, row=i)
            toggler = Toggler(btn, MY_COLOR, MY_COLOR2)
            btn.config(command=toggler)
            self.buttons.append(btn)
            self.togglers.append(toggler)


root = Tk()
my_win = Window(root)
root.mainloop()

在这种特殊情况下(现在我可以看到更多代码),我怀疑这可能是过大的,并且可以用更少的代码来完成(也许按照我认为@Nathan Hinchey目前在他的建议中所讲的内容) answer)。也就是说,我仍然认为此处显示的代码对您了解并理解Python和tkinter可能发生的事情很有帮助。

我看到@Bryan Oakley现在发布了一个answer,它使Toggler成为Button sub 类,而不是这里所示的独立类。我考虑这样做是因为这样做会更优雅-但我决定这样做可能太先进了,请按照此处所示进行操作(如我在评论中提到的那样)。除此之外,看来布莱恩(Bryan)也以一种可行的方式实现了@Nathan的想法。

答案 2 :(得分:0)

您可以循环创建按钮,并将对按钮的引用存储在字典或列表中。

非面向对象的方法

以下示例采用传统方法来完成主类中的所有工作。它使用lambda来将按钮索引传递到回调函数中。

from tkinter import *
mycolor = '#FF7F50'
mycolor2 = '#FFFFFF'
mycolor3 = '#BAF0FF'
class Window:

    def __init__(self, master):
        self.master = master
        self.master.title("Bingo")
        self.master.minsize(width=1920, height=1080)
        self.master.config(bg=mycolor3)

        self.buttons = {}
        font = ('Helvetica', 12)
        for i in range(1,10):
            button = Button(master, text=str(i), font=font,
                            height=1, width=20, bg=mycolor2,
                            command=lambda index=i: self.toggle(index))
            button.grid(column=0, row=i+1)
            self.buttons[i] = button

    def toggle(self, index):
        button = self.buttons[index]
        if button.cget('bg') == mycolor2:
            button.configure(bg=mycolor)
        else:
            button.configure(bg=mycolor2)

root = Tk()
my_win = Window(root)
root.mainloop()

注意:您可能还需要配置activebackground,以便可以看到新颜色而不必将鼠标移离按钮。

button.configure(bg=mycolor, activebackground=mycolor)

面向对象的方法

另一种解决方案是创建一个自定义按钮小部件,该部件具有内置的切换功能,这样,调用者除了创建自定义按钮的实例外无需执行任何操作。由于每个按钮都是自己知道的,因此不必告诉哪个按钮进行切换,因此这可以简化回调过程。

此示例仍然将按钮存储在字典中,尽管严格来讲在此特定示例中没有必要:

from tkinter import *
mycolor = '#FF7F50'
mycolor2 = '#FFFFFF'
mycolor3 = '#BAF0FF'
class Window:

    def __init__(self, master):
        self.master = master
        self.master.title("Bingo")
        self.master.minsize(width=1920, height=1080)
        self.master.config(bg=mycolor3)

        self.buttons = {}
        font = ('Helvetica', 23)
        for i in range(1,75):
            button = Toggler(master, text=str(i), font=font, color1=mycolor, color2=mycolor2)
            button.grid(column=0, row=i+1)
            self.buttons[i] = button


class Toggler(Button):
    def __init__(self, master, text, font, color1, color2):
        self.color1 = color1
        self.color2 = color2
        Button.__init__(self, master, text=text, font=font,
                        height=1, width=20,
                        background=color1, activebackground=color1,
                        command=self.toggle)

    def toggle(self):
        color = self.cget("background")
        new_color = self.color1 if color == self.color2 else self.color2
        self.configure(background=new_color, activebackground=new_color)


root = Tk()
my_win = Window(root)
root.mainloop()