访问绑定到事件的函数的返回值(tkinter)

时间:2011-06-02 02:02:09

标签: python events tkinter bind

基本上,我所做的是将一个click事件绑定到一个函数。例如:

self.button1.bind("<Button-1>",self.chooseDice)

我现在想要的是在另一个函数中访问chooseDice()的结果。这样做的最佳方法是什么?

class GraphicsInterface:

    #we want to initialize the game board here, set up the dice and buttons
    def __init__(self):
        self.window = Tk()
        self.window.geometry("720x500")

        #buttons under each die
        self.clicked=[] #empty list to collect all the buttons that were clicked (see chooseDice function)
        self.button1 = Button(self.window, text="Dice 1", width=13) #create the button object
        self.button1.place(x=60, y=160)  
        #bind button click event to a function (chooseDice())
        self.button1.bind("<Button-1>",self.chooseDice)

        self.button2 = Button(self.window, text="Dice 2", width=13)
        self.button2.place(x=185, y=160)
        self.button2.bind("<Button-1>",self.chooseDice)

    #using the event as an argument, append the text to the clicked list
    def chooseDice(self, event):
        self.clicked.append(event.widget.cget('text'))
        self.diceList=[] #create a new empty list
        for i in range(len(self.clicked)):
            self.diceList.append(int(self.clicked[i][5])) #get just the int value of the last character (i.e. the dice number)
        self.deactivate(event.widget)  #deactivate the button
        return self.diceList

3 个答案:

答案 0 :(得分:1)

只需在您的班级中添加self.result属性,并将其设置为chooseDice()

答案 1 :(得分:1)

重构。将其分为两个功能。

一个返回正确的结果,可供其他对象使用。

另一个绑定到GUI控件,并使用正确的结果来激活和停用GUI对象。

确实,你应该始终这样做。你应该总是拥有能够执行普通Python工作的函数,无需GUI即可正常工作,并且可以在没有GUI的情况下进行单元测试。然后将这个工作“模型”连接到GUI。

答案 2 :(得分:1)

你已经在做你需要做的事了。您的示例代码将self.diceList设置为某个值。您可以在代码中的任何其他位置直接使用self.diceList

顺便说一下 - 你编写的代码随着时间的推移很难维护。例如,如果您将骰子标签更改为“Dice One”或简单地“One”而不是“Dice 1”,该怎么办?或者,随着您的应用程序的进展,您可能需要图形图像而不是按钮上的文本。您必须修改解析按钮名称的代码。您实际上是在按钮标签中编码信息,这不是一个好主意。

一个简单的解决方案,也使您的chooseDice方法更简单,更容易理解,是传递回调中的骰子数。例如:

self.button1.configure(command=lambda btn=self.button1: self.chooseDice(btn, 1))

以上将两个参数传递给chooseDice方法:按钮实例(因此可以禁用它)和按钮编号(这样您就不必解析按钮名称来获取它)

这也允许您在循环中创建骰子,而不是硬编码同一代码块的多个副本。这是一个完整的工作示例:

from Tkinter import *

class GraphicsInterface:

    def __init__(self):
        self.window = Tk()
        self.window.geometry("720x500")
        self.clicked=[] 
        self.buttons = []

        for n in range(1, 3):
            btn = Button(text="Button " + str(n))
            btn.configure(command=lambda btn=btn, n=n: self.chooseDice(btn, n))
            btn.pack()
            self.buttons.append(btn)

        btn = Button(text="Go!", command=self.go)
        btn.pack()
        self.window.mainloop()


    def go(self):
        print "buttons:", self.clicked
        self.reset()

    def reset(self):
        '''Reset all the buttons'''
        self.clicked = []
        for button in self.buttons:
            button.configure(state="normal")

    def chooseDice(self, widget, number):
        self.clicked.append(number)
        widget.configure(state="disabled")

app = GraphicsInterface()

最后,最后一些建议:

不要使用place,它会使您的GUI更难创建,并且它们不会对窗口大小的变化,字体的变化,平台的变化等做出很好的反应。使用packgrid代替。另外,不要创建固定宽度的按钮。同样,这是为了更好地处理字体的变化。有时您需要固定宽度按钮,但看起来您的代码没有任何理由使用它们。

最后,我不知道你实际想要完成什么,但通常如果你使用按钮来跟踪状态(是否按下这个东西?)你想使用复选框(选择N的N)或radiobuttons(选择N中的1)。您可能需要考虑切换到那些而不是按钮。