доступ к возвращаемому значению функции, которая была связана с событием (tkinter) - PullRequest
3 голосов
/ 02 июня 2011

По сути, я связал событие 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 ]

1 голос
/ 02 июня 2011

Рефакторинг.Разделите это на две функции.

Одна возвращает правильный результат, используемый другими объектами.

Другая связана с элементом управления GUI и использует правильный результат для активации и деактивации объектов GUI.

Действительно, вы должны всегда делать это.У вас всегда должны быть функции, которые выполняют обычные функции Python, работают правильно без графического интерфейса и могут тестироваться модульно без графического интерфейса.Затем вы подключаете эту рабочую «модель» к графическому интерфейсу.

1 голос
/ 02 июня 2011

Вы уже делаете то, что вам нужно сделать. Ваш пример кода устанавливает 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, это затрудняет создание ваших графических интерфейсов, и они не будут хорошо реагировать на изменения размера окна, изменения шрифта, изменения платформы и т. Д. Используйте pack и grid вместо. Кроме того, не создавайте кнопки фиксированной ширины. Опять же, это для лучшей обработки изменений в шрифтах. Есть моменты, когда вам нужны кнопки фиксированной ширины, но не похоже, что у вашего кода есть основания их использовать.

Наконец, я не знаю, чего вы на самом деле пытаетесь достичь, но обычно, если вы используете кнопки для отслеживания состояния (нажата эта штука или нет?), Вы хотите использовать флажки (выберите N из N) или радиокнопки (выберите 1 из N). Возможно, вы захотите переключиться на них вместо кнопок.

1 голос
/ 02 июня 2011

просто добавьте атрибут self.result в свой класс и установите его на chooseDice()

...