Не работает метод bind кнопки в tkinter

Владимир Мельниченко

Новичок
Пользователь
Сен 16, 2022
3
0
1
Вызов метода bind у кнопки дает ошибку : AttributeError: 'NoneType' object has no attribute 'bind' . type этой кнопки (внутри функции) дает <class 'NoneType'>, тогда как type кнопки в основном теле программы дает <class 'tkinter.Button'> . Windows10, python 3.10.6 .
Python:
from tkinter import *
import time

def f1(event):

    w = Toplevel()
    w.geometry('180x130')
    w.title('Фигура')
    
    lbl_x1 = Label(w,text='x1').grid(row=0,column=0,padx=10)
    lbl_x2 = Label(w,text='x2').grid(row=1,column=0,padx=10)
    lbl_y1 = Label(w,text='y1').grid(row=0,column=2,padx=5)
    lbl_y2 = Label(w,text='y2').grid(row=1,column=2,padx=5)
    ent_x1 = Entry(w,width=6).grid(row=0,column=1,padx=5)
    ent_x2 = Entry(w,width=6).grid(row=1,column=1,padx=5)
    ent_y1 = Entry(w,width=6).grid(row=0,column=3,padx=5)
    ent_y2 = Entry(w,width=6).grid(row=1,column=3,padx=5)

    r_var = BooleanVar()
    r_var.set(0)
    r1 = Radiobutton(w,text='Прямоугольник',
                 variable=r_var, value=0).grid(row=2,column=0,columnspan=4,
                                               sticky=W,padx=10)
    r2 = Radiobutton(w,text='Овал',
                 variable=r_var, value=1).grid(row=3,column=0,columnspan=4,
                                               sticky=W,padx=10)

    btn2 = Button(w,text='Нарисовать').grid(row=4,column=0,columnspan=4)
    print(type(btn2))
    btn2.bind('<Button-1>',f3)
    
def f2(event,x1,y1,x2,y2,value):
    w.destroy()

def f3(event):
    pass


root = Tk()
root.title('Главное окно')

c = Canvas(root, width=400, height=400, bg='white')
c.grid(row=0,column=0)
 
btn = Button(text='Добавить фигуру')
print(type(btn))
btn.bind('<Button-1>',f1)
btn.grid(row=1,column=0)

root.mainloop()
 

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 583
457
83
Если можно, поясните, почему в lambda-функцию нельзя передавать значения entry.get(), если константы и обычные переменные передаются без проблем ?
entry.get() тоже передается и выполняется при вызове, вы не успеваете ничего туда ввести, и поэтому там пустая строка...
 

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 583
457
83
bind нужен для привязки функции к физической кнопке - например, пробел, интер или левая кнопка мыши...
чтобы привязать функцию к кнопке в гуи, нужно у кнопки использовать атрибут command
Python:
from tkinter import *
import time


def f1():
    w = Toplevel()
    w.geometry('180x130')
    w.title('Фигура')

    lbl_x1 = Label(w, text='x1').grid(row=0, column=0, padx=10)
    lbl_x2 = Label(w, text='x2').grid(row=1, column=0, padx=10)
    lbl_y1 = Label(w, text='y1').grid(row=0, column=2, padx=5)
    lbl_y2 = Label(w, text='y2').grid(row=1, column=2, padx=5)
    ent_x1 = Entry(w, width=6).grid(row=0, column=1, padx=5)
    ent_x2 = Entry(w, width=6).grid(row=1, column=1, padx=5)
    ent_y1 = Entry(w, width=6).grid(row=0, column=3, padx=5)
    ent_y2 = Entry(w, width=6).grid(row=1, column=3, padx=5)

    r_var = BooleanVar()
    r_var.set(0)
    r1 = Radiobutton(w, text='Прямоугольник',
                     variable=r_var, value=0).grid(row=2, column=0, columnspan=4,
                                                   sticky=W, padx=10)
    r2 = Radiobutton(w, text='Овал',
                     variable=r_var, value=1).grid(row=3, column=0, columnspan=4,
                                                   sticky=W, padx=10)

    btn2 = Button(w, text='Нарисовать').grid(row=4, column=0, columnspan=4)
    print(type(btn2))
    # btn2.bind('<Button-1>', f3)


def f2(event, x1, y1, x2, y2, value):
    w.destroy()


def f3(event):
    pass


root = Tk()
root.title('Главное окно')

c = Canvas(root, width=400, height=400, bg='white')
c.grid(row=0, column=0)

btn = Button(text='Добавить фигуру', command=f1)
print(type(btn))
# btn.bind('<Button-1>', f1)
btn.grid(row=1, column=0)

root.mainloop()
 

Владимир Мельниченко

Новичок
Пользователь
Сен 16, 2022
3
0
1
Переделал вызов функции через атрибут command. Если вызывается функция без параметров (f3), то все работает нормально. Если пытаюсь передать в функцию (f2) содержимое полей ввода, получая их через get(), генерируется ошибка, что у объекта неопределенного типа нет атрибута get() :

AttributeError: 'NoneType' object has no attribute 'get'

Все виджеты дочернего окна почему-то имеют тип 'NoneType' . Что нужно сделать ?
Python:
from tkinter import *
import time

def f1(event):

    global w
    w = Toplevel()
    w.geometry('180x130+250+250')
    w.title('Фигура')
    
    lbl_x1 = Label(w,text='x1').grid(row=0,column=0,padx=10)
    lbl_x2 = Label(w,text='x2').grid(row=1,column=0,padx=10)
    lbl_y1 = Label(w,text='y1').grid(row=0,column=2,padx=5)
    lbl_y2 = Label(w,text='y2').grid(row=1,column=2,padx=5)
    ent_x1 = Entry(w,width=6).grid(row=0,column=1,padx=5)
    ent_x2 = Entry(w,width=6).grid(row=1,column=1,padx=5)
    ent_y1 = Entry(w,width=6).grid(row=0,column=3,padx=5)
    ent_y2 = Entry(w,width=6).grid(row=1,column=3,padx=5)

    r_var = BooleanVar()
    r_var.set(0)
    r1 = Radiobutton(w,text='Прямоугольник',
                 variable=r_var, value=0).grid(row=2,column=0,columnspan=4,
                                               sticky=W,padx=10)
    r2 = Radiobutton(w,text='Овал',
                 variable=r_var, value=1).grid(row=3,column=0,columnspan=4,
                                               sticky=W,padx=10)

#    btn2 = Button(w,text='Нарисовать',command=f3).grid(row=4,column=0,columnspan=4)
    
    btn2 = Button(w,text='Нарисовать',command=lambda x1=int(ent_x1.get()),
        y1=int(ent_y1.get()), x2=int(ent_x2.get()),
        y2=int(ent_x2.get()), value=r_var.get(): f2(x1,y1,x2,y2,value)).grid(row=4,column=0,columnspan=4)

            
def f2(x1,y1,x2,y2,value):
    w.destroy()
    if value == 0:
        c.create_rectangle(x1, y1, x2, y2)
    else:   
        c.create_oval(x1, y1, x2, y2)

def f3():
    w.destroy()
    c.create_rectangle(10, 10, 50, 50)   
    c.create_oval(100, 100, 150, 150)


root = Tk()
root.title('Главное окно')
root.geometry('+150+150')

c = Canvas(root, width=400, height=400, bg='white')
c.grid(row=0,column=0)
 
btn = Button(text='Добавить фигуру')
# print(type(btn))
btn.bind('<Button-1>',f1)
btn.grid(row=1,column=0)

root.mainloop()
 

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 583
457
83
функция grid ничего не возвращает, то есть NoneType, нужно поделить операции
Python:
ent_x1 = Entry(w, width=6)
ent_x2 = Entry(w, width=6)
ent_y1 = Entry(w, width=6)
ent_y2 = Entry(w, width=6)
ent_x1.grid(row=0, column=1, padx=5)
ent_x2.grid(row=1, column=1, padx=5)
ent_y1.grid(row=0, column=3, padx=5)
ent_y2.grid(row=1, column=3, padx=5)

ну и дальше у вас будет еще ошибка, что пустую строку нельзя привести к инту, вам нужно отдельную функцию сделать для кнопки нарисовать, где вы будете получать текст из этих полей
 

Владимир Мельниченко

Новичок
Пользователь
Сен 16, 2022
3
0
1
Спасибо за консультацию, переделал, все заработало. Если можно, поясните, почему в lambda-функцию нельзя передавать значения entry.get(), если константы и обычные переменные передаются без проблем ?
Python:
from tkinter import *
import time

def f1(event):

    global w, ent_x1, ent_x2, ent_y1, ent_y2, r_var
    w = Toplevel()
    w.geometry('180x130+250+250')
    w.title('Фигура')
    
    lbl_x1 = Label(w,text='x1')
    lbl_x1.grid(row=0,column=0,padx=10)
    lbl_x2 = Label(w,text='x2')
    lbl_x2.grid(row=1,column=0,padx=10)
    lbl_y1 = Label(w,text='y1')
    lbl_y1.grid(row=0,column=2,padx=5)
    lbl_y2 = Label(w,text='y2')
    lbl_y2.grid(row=1,column=2,padx=5)
    ent_x1 = Entry(w,width=6)
    ent_x1.grid(row=0,column=1,padx=5)
    ent_x2 = Entry(w,width=6)
    ent_x2.grid(row=1,column=1,padx=5)
    ent_y1 = Entry(w,width=6)
    ent_y1.grid(row=0,column=3,padx=5)
    ent_y2 = Entry(w,width=6)
    ent_y2.grid(row=1,column=3,padx=5)

    r_var = BooleanVar()
    r_var.set(0)
    
    r1 = Radiobutton(w,text='Прямоугольник',
                 variable=r_var, value=0)
    r1.grid(row=2,column=0,columnspan=4,sticky=W,padx=10)
    r2 = Radiobutton(w,text='Овал',
                 variable=r_var, value=1)
    r2.grid(row=3,column=0,columnspan=4,sticky=W,padx=10)

    Button(w,text='Нарисовать',command=f4).grid(row=4,column=0,columnspan=4)
                
def f4():
    x1 = int(ent_x1.get())
    x2 = int(ent_x2.get())
    y1 = int(ent_y1.get())
    y2 = int(ent_y2.get())
    w.destroy()
    if r_var.get() == 0:
        c.create_rectangle(x1, y1, x2, y2)
    else:   
        c.create_oval(x1, y1, x2, y2)
    
root = Tk()
root.title('Главное окно')
root.geometry('+150+150')

c = Canvas(root, width=400, height=400, bg='white')
c.grid(row=0,column=0)
 
btn = Button(text='Добавить фигуру')
btn.bind('<Button-1>',f1)
btn.grid(row=1,column=0)

root.mainloop()
 

Форум IT Специалистов