【问题标题】:Tkinters highlight of button is not working for me按钮的 Tkinters 突出显示对我不起作用
【发布时间】:2019-10-11 19:26:16
【问题描述】:

根据this post 上接受的答案,在按钮上使用.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()

生成的应用程序:

通过一些广泛的搜索,我在highlightbackground 上找不到太多关于同一问题的 Q/A,所以可能缺少一些东西。我还尝试将焦点设置为 this documentation 状态小部件需要焦点,但结果相同。

可能与版本或操作系统有关...

操作系统 - Windows 10 专业版

Python - 3.6.2

使用 Krrr 的帖子更新了示例。所以现在这确实有点用,但是这里的问题是它正在调整按钮的大小并且没有提供正确的突出显示颜色。

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()

结果:

期望:

【问题讨论】:

  • 您的代码在 OSX 上工作:我看到红色突出显示颜色。
  • @BryanOakley Hum。不能在我的工作电脑上工作。回家后我会在 3.7 上测试。
  • 就其价值而言,它也不适用于我的 Windows 10 Python 3.7.4。我认为你不会有太多的运气。似乎与操作系统相关。
  • @Krrr 感谢您的意见。在这一点上,这听起来像是一个操作系统问题。
  • 我将添加一个观察 - 按钮大小对我来说似乎是可疑的。在您链接到的答案中,按钮之间有间距,但是当我运行代码时,按钮会扩展至最大,没有间隙。与您当前的示例相同。

标签: python tkinter


【解决方案1】:

不幸的是,Windows 操作系统似乎没有正确触发 statedefault 小部件配置。但是,这可以通过您自己的绑定来实现。

如果您只有少数需要这种行为的小部件,您可以创建一个小部件包装器:

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')

# ...

我认为这更像是一种 hacky 方法。

编辑:为了完整起见,这里是一个使用 bind_class 的 MCVE:

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()

【讨论】:

  • 哼。好吧,除非我使用focus(),否则我只会得到多个无边框按钮。这个想法是高亮会在按钮点击时改变。
  • 您的意思是您希望highlightbackground 颜色在焦点移开时显示?是的,那一点我也想弄清楚,不知道为什么那个特定的设置没有被触发。
  • 是的。这是主要的斗争。我在您的 lambda 中添加了一条打印语句以进行测试,它可能有助于排除故障。 w.bind(k, lambda e, kwarg=v: (e.widget.config(**kwarg), print('test{} - {}'.format(e, kwarg))))
  • 所以我们的目标是复制这篇文章的预期功能。 stackoverflow.com/questions/53647343/…。如果不能在窗口上显示高亮,那么它将无法工作。
  • 如果您只需要功能,一个肮脏的方法是保留按钮的default='active',而只是将highlighcolor 更改为焦点,尽管不是预期的方法,但它会达到相同的效果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-17
  • 2013-04-20
  • 1970-01-01
  • 1970-01-01
  • 2015-09-27
  • 1970-01-01
相关资源
最近更新 更多