Подсветка кнопки Tkinters не работает для меня - PullRequest
0 голосов
/ 11 октября 2019

В соответствии с принятым ответом на в этом посте использование .configure(highlightbackground='red') на кнопке должно применять цвет вокруг кнопки, однако при тестировании я не могу воспроизвести то, что плакат продемонстрировал в своей записи GIF.

Вот мой тестовый пример: (Обратите внимание, даже при копировании со вставкой кода плакатов я не могу получить эффект выделения, который они показывают)

import tkinter as tk


root = tk.Tk()

btn = tk.Button(root, text='test', bg="#000000", fg="#ffffff", highlightthickness=4, activebackground="#ffffff",
                activeforeground="#000000", highlightbackground='red', highlightcolor='red')
btn.pack()
btn.focus_set()
root.mainloop()

Результирующее приложение:

enter image description here

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

Возможно, это может быть версия или ОС, связанная ...

ОС - Windows 10 Pro

Python - 3.6.2

Обновлен пример с использованием сообщения Кррра. Так что теперь это работает, но проблема здесь в том, что она изменяет размер кнопки и не обеспечивает правильный выделенный цвет.

import tkinter as tk


def ResponsiveWidget(widget, *args, **kwargs):
    bindings = {
        '<FocusIn>': {'highlightbackground': 'red', 'highlightcolor':'red'},
        '<FocusOut>': {'highlightbackground': '#d9d9d9', 'highlightcolor':'SystemButtonFace'},
        '<Enter>': {'state': 'active'},
        '<Leave>': {'state': 'normal'}
    }
    for k, v in bindings.items():
        root.bind_class('Button', k, lambda e, kwarg=v: e.widget.config(**kwarg))


def update_active(event):
    global previous_button
    if previous_button != event.widget:
        previous_button.config(default='normal')
        event.widget.config(default='active')
        previous_button = event.widget


root = tk.Tk()
button_list = []
previous_button = None

for i in range(5):
    if i == 0:
        button_list.append(tk.Button(root, text='test', bg="#000000", fg="#ffffff", highlightthickness=5,
                                     activebackground="#ffffff", activeforeground="#000000", default='active'))
        previous_button = button_list[-1]
    else:
        button_list.append(tk.Button(root, text='test', bg="#000000", fg="#ffffff", highlightthickness=5,
                                     activebackground="#ffffff", activeforeground="#000000", default='normal'))
    button_list[-1].pack(padx=5, pady=5)
    button_list[-1].bind('<ButtonRelease-1>', update_active)

root.mainloop()

Результаты:

enter image description here

Ожидание:

enter image description here

1 Ответ

1 голос
/ 15 октября 2019

К сожалению, похоже, что ОС Windows не запускает настройки виджетов state и default должным образом. Однако этого можно достичь, выполнив свои собственные привязки.

Если у вас есть только несколько виджетов, которым требуется такое поведение, вы можете создать оболочку виджета:

def ResponsiveWidget(widget, *args, **kwargs):
    bindings = {
        '<FocusIn>': {'default':'active'},    # for Keyboard focus
        '<FocusOut>': {'default': 'normal'},  
        '<Enter>': {'state': 'active'},       # for Mouse focus
        '<Leave>': {'state': 'normal'}
    }
    # Create the widget instance
    w = widget(*args, **kwargs)

    # Set the bindings for the widget instance
    for k, v in bindings.items():
        w.bind(k, lambda e, kwarg=v: e.widget.config(**kwarg))

    # Remember to return the created and binded widget
    return w

btn = ResponsiveWidget(tk.Button, root, text='test3', bg="#000000", fg="#ffffff", highlightthickness=10, activebackground="#ffffff",
                activeforeground="#000000", highlightbackground='red', highlightcolor='green')

btn2 = ResponsiveWidget(tk.Button, root, text='test4', bg="#000000", fg="#ffffff", highlightthickness=10, activebackground="#ffffff",
                activeforeground="#000000", highlightbackground='green', highlightcolor='red')

С другой стороны, если вы хотите, чтобы весь класс виджета всегда правильно запускал состояние по умолчанию / состояние, вместо этого вы можете использовать bind_class:

bindings = {
    '<FocusIn>': {'default':'active'},    # for Keyboard focus
    '<FocusOut>': {'default': 'normal'},  
    '<Enter>': {'state': 'active'},       # for Mouse focus
    '<Leave>': {'state': 'normal'}
}
for k, v in bindings.items():
    root.bind_class('Button', k, lambda e, kwarg=v: e.widget.config(**kwarg))

Это, кажется, вызывает события просто отлично.

Если вы просто хотите повторить функциональность цвета подсветки, менее желательным методом было бы вместо этого изменить конфигурацию highlightcolor на фокусе:

bindings = {
        '<FocusIn>': {'highlightcolor':'red'},
        '<FocusOut>': {'highlightcolor': 'SystemButtonFace'},
        '<Enter>': {'state': 'active'},
        '<Leave>': {'state': 'normal'}
    }
for k, v in bindings.items():
    root.bind_class('Button', k, lambda e, kwarg=v: e.widget.config(**kwarg))

# Note this method requires you to set the default='active' for your buttons

btn = tk.Button(root, text='test', bg="#000000", fg="#ffffff", highlightthickness=10, activebackground="#ffffff",
                activeforeground="#000000", highlightcolor='SystemButtonFace', default='active')

# ...

Я бы посчитал это более хакерским методом.

Редактировать: Для полноты вот MCVE, использующий bind_class:

import tkinter as tk

root = tk.Tk()
bindings = {
        '<FocusIn>': {'highlightcolor':'red'},
        '<FocusOut>': {'highlightcolor': 'SystemButtonFace'},
        '<Enter>': {'state': 'active'},
        '<Leave>': {'state': 'normal'}
    } 

for k, v in bindings.items():
    root.bind_class('Button', k, lambda e, kwarg=v: e.widget.config(**kwarg))

btns = list(range(5))
for btn in btns:
    btns[btn] = tk.Button(root, text='test', bg="#000000", fg="#ffffff", highlightthickness=5, activebackground="#ffffff",
        activeforeground="#000000", highlightcolor='SystemButtonFace', default='active', padx=5, pady=5)
    btns[btn].pack()

btns[0].focus_set()
root.mainloop()

И MCVE, использующий ResponsiveWidget функцию:

import tkinter as tk

root = tk.Tk()
def ResponsiveWidget(widget, *args, **kwargs):
    bindings = {
        '<FocusIn>': {'highlightcolor':'red'},    # for Keyboard focus
        '<FocusOut>': {'highlightcolor': 'SystemButtonFace'},  
        '<Enter>': {'state': 'active'},       # for Mouse focus
        '<Leave>': {'state': 'normal'}
    }
    # Create the widget instance
    w = widget(*args, **kwargs)

    # Set the bindings for the widget instance
    for k, v in bindings.items():
        w.bind(k, lambda e, kwarg=v: e.widget.config(**kwarg))

    # Remember to return the created and binded widget
    return w

btns = list(range(5))
for btn in btns:
    btns[btn] = ResponsiveWidget(tk.Button, root, text=f'test{btn}', bg="#000000", fg="#ffffff", highlightthickness=10, activebackground="#ffffff",
        activeforeground="#000000", highlightcolor='SystemButtonFace', default='active', padx=5, pady=5)
    btns[btn].pack()

btns[0].focus_set()
root.mainloop()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...