python tkinter левый щелчок мыши работает только с двойным щелчком - PullRequest
1 голос
/ 06 августа 2020

С приведенным ниже кодом Button-1 вызывается щелчок relief изменение работает только тогда, когда оно уже нажито один раз (только двойной щелчок работает 1-й раз, 2-й раз - нормально, но если выбран другой виджет, то же самое происходит) :

def selected(event):
    event.widget.config(relief=SUNKEN if event.widget.cget("relief") == "raised" else RAISED)    

B1 = Button(root, text ='BUTTON1', font='-size 8', relief=RAISED)
B1.bind("<Button>", selected)
B1.grid(row = 1, column = 2, sticky = N+E+S+W)

B2 = Button(root, text ='BUTTON2', font='-size 8', relief=RAISED)
B2.bind("<Button>", selected)
B2.grid(row = 2, column = 2, sticky = N+E+S+W)

С Button-2 и Button-3 он работает правильно,

В чем причина?

Ответы [ 2 ]

2 голосов
/ 06 августа 2020

Проблема в том, что tkinter может связывать многие функции с событием, и уже есть привязанная функция по умолчанию, которая изменилась relief при нажатии кнопки. Вы можете использовать return "break" в своей функции, чтобы сообщить tkinter, что вы обработали это событие, и оно пропустит другие функции.

Или вы можете использовать стандартный command= для функции проверки, а затем он пропустит другую функцию .

import tkinter as tk  # PEP8: `import *` is not preferred
 
# --- functions ---

def selected1(event):
    event.widget.config(relief='sunken' if event.widget.cget('relief') == 'raised' else 'raised')    
    return "break"

def selected2():
    B2.config(relief='sunken' if B2.cget("relief") == 'raised' else 'raised')    

# --- main ---

root = tk.Tk()

B1 = tk.Button(root, text='BUTTON1', relief='raised')
B1.bind("<Button>", selected1)
B1.grid(row=1, column=2, sticky='news')

B2 = tk.Button(root, text='BUTTON2', relief='raised', command=selected2)
B2.grid(row=2, column=2, sticky='news')

root.mainloop()  

То же, используя for -l oop и lambda.

Обычно используется только ссылка на button, значение которого изменяется в l oop поэтому, наконец, все функции используют ссылку на одно и то же значение - последнее значение, присвоенное в l oop.

Используя lambda arg=button, он создает новую переменную в каждом l oop и копирует значение из button в arg, поэтому каждый виджет использует разные аргументы с разными значениями.

import tkinter as tk  # PEP8: `import *` is not preferred
 
# --- functions ---

def selected(widget):
    widget.config(relief='sunken' if widget.cget('relief') == 'raised' else 'raised')    

# --- main ---

root = tk.Tk()

for x in range(1, 6):
    button = tk.Button(root, text=f'LOOP BUTTON {x}', relief='raised')
    #button.config(command=lambda arg=button:selected3(arg))
    button['command'] = lambda arg=button:selected(arg)
    button.grid(row=x, column=2, sticky='news')

root.mainloop()  

Как указано в комментарии @ acw1668, вы также можете использовать Checkbutton(..., indicator=False), чтобы получить тот же эффект без дополнительной функции

import tkinter as tk  # PEP8: `import *` is not preferred
 
# --- main ---

root = tk.Tk()

for x in range(1, 6):
    button = tk.Checkbutton(root, text=f'LOOP BUTTON {x}', indicator=False, padx=10, pady=5)
    button.grid(row=x, column=2, sticky='news')

root.mainloop()  
0 голосов
/ 06 августа 2020

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

def selected(event):
    event.widget.config(relief=SUNKEN if event.widget.cget("relief") == "raised" else RAISED)    

B1 = Button(root, text ='BUTTON1', font='-size 8', relief=RAISED)
B1.bind("<Button-1>", selected)
B1.grid(row = 1, column = 2, sticky = N+E+S+W)

B2 = Button(root, text ='BUTTON2', font='-size 8', relief=RAISED)
B2.bind("<Button-1>", selected)
B2.grid(row = 2, column = 2, sticky = N+E+S+W)

Просто измените «Button» на «Button-1» и сообщите мне, есть ли ошибки

...