Найти - Пользователи
Полная версия: Не вызывается при нажатии на кнопку.
Начало » Python для новичков » Не вызывается при нажатии на кнопку.
1
megabax
Добрый день. Выполняю такой код:
 from tkinter import * 
class Calculator(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent
        print("11111")
        self.setUI() 
    def button_clicked(self, event):
        print("event")
        self.output.delete("0.0","end") 
        self.output.insert("0.0","sdfdsfsd")
    def setUI(self):
        print("UI")
        self.pack(fill=BOTH, expand=1)
        self.output=Text(self, height=1, width=25)
        self.output.grid(row=0, column=0, columnspan = 5)
        #i=0
        #currow=1
        #while i<=9:
        #    if i>=5:
        #        currow=2
        #    btn = Button(self, text=i, width=3)
        #    btn.grid(row=currow, column=i % 5)
        #    btn.bind("Button-",self.button_clicked) 
        #    i=i+1
        btn = Button(self, text="Кнопка", width=10, command=self.button_clicked)
        btn.grid(row=1, column=0)
        #btn.bind("Button-1",self.button_clicked)         
        print("end UI")
def main():
    root = Tk()
    root.geometry("1500x900")
    #root.textvar=root.StringVar()
    app = Calculator(root)
    root.mainloop() 
if __name__ == "__main__":
    print("start")
    main()
    

При нажатии на кнопочку вылазит сообщение об ошибке:
Traceback (most recent call last):
File “D:\Самообразование\Питон\Calk1.py”, line 41, in <module>
main()
File “D:\Самообразование\Питон\Calk1.py”, line 36, in main
app = Calculator(root)
File “D:\Самообразование\Питон\Calk1.py”, line 8, in __init__
self.setUI()
File “D:\Самообразование\Питон\Calk1.py”, line 27, in setUI
btn = Button(self, text=“Кнопка”, width=10, command=self.button_clicked(btn))
UnboundLocalError: local variable ‘btn’ referenced before assignment
Подскажите, пожалуйста, что делаю не так?
4kpt_IV
Не обманывайте. Вы не этот код выполняете. Вы пытаетесь повесить на событие в качестве обработчика результат выполнения функции, а не объект функции.

 btn = Button(self, text=“Кнопка”, width=10, command=self.button_clicked(btn))

Для того, чтобы делать такие фокусы нужно использовать lambda

 btn = Button(self, text=“Кнопка”, width=10, command=lambda event: self.button_clicked(btn))
megabax
Сделал вот так:
 btn = Button(self, text="Кнопка", width=10, command=lambda event: self.button_clicked(btn))
И вот такой обработчик:
     def button_clicked(self,event):
        print("event")
        self.output.delete("0.0","end") 
        self.output.insert("0.0","sdfdsfsd")
Теперь он говорит:
Exception in Tkinter callback
Traceback (most recent call last):
File “C:\Users\pc1\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py”, line 1550, in __call__
return self.func(*args)
TypeError: <lambda>() missing 1 required positional argument: ‘event’
Если я делаю вот так:
 btn = Button(self, text="Кнопка", width=10, command=self.button_clicked)
и так
     def button_clicked(self):
        print("event")
        self.output.delete("0.0","end") 
        self.output.insert("0.0","sdfdsfsd")
То все нормально отрабатывает. Но мне надо каким-то волшебным образом передать в обработчик события параметр или ссылку на то, какая кнопка была нажата.
megabax
А, спасибо, понял сам, ссылку на еще не созданную кнопку видимо нельзя передавать, надо так:
 btn = Button(self, text="Кнопка", width=10, command=lambda: self.button_clicked(1))
и
     def button_clicked(self, event):
        print("event")
        print(event)
        self.output.delete("0.0","end") 
        self.output.insert("0.0","sdfdsfsd")
megabax
Зато не получается так сделать:
     def setUI(self):
        print("UI")
        self.pack(fill=BOTH, expand=1)
        self.output=Text(self, height=1, width=25)
        self.output.grid(row=0, column=0, columnspan = 5)
        i=0
        currow=1
        while i<=9:
            if i>=5:
                currow=2
            btn = Button(self, text=i, width=3, command=lambda: self.button_clicked(i))
            btn.grid(row=currow, column=i % 5)
            #btn.bind("Button-",self.button_clicked) 
            i=i+1
        #btn = Button(self, text="Кнопка", width=10, command=lambda: self.button_clicked(1))
        #btn.grid(row=1, column=0)
        #btn.bind("Button-1",self.button_clicked)         
        print("end UI")
Почему-то передаётся только последнее значение 10, а надо чтобы каждая кнопка сообщала свою цифру.
4kpt_IV
Это фокус lambda. Описывайте явно.

 btn = Button(self, text=i, width=3, command=lambda i=i: self.button_clicked(i))
4kpt_IV
Ну и вообще не надо это передавать.
Попробуйте в функции обработчике

 #
def button_clicked(self, event):
        print(event.widget["text"])

И будете очень удивлены
megabax
Спасибо большое.
Вот так работает:
 btn = Button(self, text=i, width=3, command=lambda i=i: self.button_clicked(i))
Про последнее, я, правда, не совсем понял: откуда возьмётся event со свойством widget? Если я ничего не передаю, то у меня в функции не может быть два аргумента, на такой обработчик интерпретатор ругается
TypeError: button_clicked() missing 1 required positional argument: ‘event’
4kpt_IV
А Вы не передавайте ничего Event валится в функцию при использовании bind по-умолчанию. На command его не будет.

Вот

 Button(self, text=i, width=3).bind("<Button-1>", button_clicked)
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB