【问题标题】:Tkinter selected Entry() and Spinbox() field text background and foreground when not in focusTkinter 在未聚焦时选择了 Entry() 和 Spinbox() 字段文本背景和前景
【发布时间】:2020-10-13 14:41:54
【问题描述】:

我正在使用 tkiner ttk 小部件并使用 ttk.Style() 配置所有内容。 When I use the 'clam' theme, widgets like ttk.Entry() and ttk.Spinbox() have this default setting that when text is selected but the widget is not in focus anymore the background of the text is gray and the foreground is white.这是一个视觉示例,当光标已经在输入行中时,但旋转框中的文本仍然具有一些自定义颜色。 The coloring of the text goes back to unselected style only when text in other widget is selected

我一直在寻找如何改变它。我发现的最接近的是tk.Text() 小部件实际上有inactiveselectbackground 的这个选项(没有inactiveselectforeground tho)。但这不适用于ttk.Entry()ttk.Spinbox()。 此外,当使用常规 tk.Entry()tk.Spinbox() 或使用 ttk 小部件的默认主题时,背景和前景不会更改为新颜色。我想这些选项可能仍然存在,但它们没有设置为任何特定的东西。

回到具体问题 - 有谁知道当小部件不再处于焦点时是否可以更改 ttk.Entry()ttk.Spinbox() 中文本的背景和前景颜色?也许可以解决这个问题?

【问题讨论】:

  • 您可以使用 bind "<FocusIn>""<FocusOut>" 来实现类似的效果。
  • 我也想过这个问题,我也尝试了 style.map() 选项。但是绑定"<FocusIn>""<FocusOut>" 仍然需要更改该小部件的特定属性。我找不到那个属性。
  • 您到底想改变什么? ForegroundBackground 的 entry 和 spinbox 小部件在不活动时(焦点)?
  • 是的,没错。

标签: python tkinter ttk


【解决方案1】:

要在小部件处于非活动状态(不在焦点上)时更改 foregroundbackground,然后在 绑定的帮助下,我们可以在这样他们就会在失去焦点和重新获得焦点时改变他们的foregroundbackground

实际上,我们可以先保存该小部件的原始foregroundbackground 值,然后使用它 回调。

在这里,我创建了一个完全符合您要求的类条目。我添加了inactivebackgroundinactiveforeground 配置选项。

class Entry(tk.Entry):
    def __init__(self, master=None, **kw):
        self.inactivebackground = kw.pop('inactivebackground', 'white')
        self.inactiveforeground = kw.pop('inactiveforeground', 'black')
        super().__init__(master=master, **kw)
        self.org_bg = self['background']
        self.org_fg = self['foreground']
        self.bind('<FocusIn>', self._focusin, '+')
        self.bind('<FocusOut>', self._focusout, '+')
        self._focusout()

    def _focusout(self, evt=None):
        self['background'] = self.inactivebackground
        self['foreground'] = self.inactiveforeground
    
    def _focusin(self, evt=None):
        self['background'] = self.org_bg
        self['foreground'] = self.org_fg

看看这个例子:-

import tkinter as tk

root = tk.Tk()

var = tk.StringVar(value="Hello! How are you doing! :)")

Entry(root, textvariable=var, inactivebackground='pink', 
      inactiveforeground='blue').pack()
Entry(root, textvariable=var, inactivebackground='orange', 
      inactiveforeground='red').pack()

root.mainloop()

同样,您可以修改Spinbox 来做同样的事情。同样,只需将继承的类 tk.Entry 替换为 ttk.Entry 也可以与 ttk 样式小部件一起使用,但请记住并非所有内容都可以直接使用 ttk 样式小部件进行配置。


继承的力量

您可以采取一个技巧来节省时间和空间,通过创建一个可以与所需小部件一起继承的支持类以具有相同的功能。

class supportinactive(object):
    def __init__(self, inactivebackground, inactiveforeground):
        self.inactivebackground = inactivebackground
        self.inactiveforeground = inactiveforeground
        self.org_bg = self['background']
        self.org_fg = self['foreground']
        self.bind('<FocusIn>', self._focusin, '+')
        self.bind('<FocusOut>', self._focusout, '+')
        self._focusout()

    def _focusout(self, evt=None):
        self['background'] = self.inactivebackground
        self['foreground'] = self.inactiveforeground
    
    def _focusin(self, evt=None):
        self['background'] = self.org_bg
        self['foreground'] = self.org_fg

怎么用?

从上面的supportinactive 类中,我们可以像这样将这个功能添加到小部件中

class Entry(tk.Entry, supportinactive):
    def __init__(self, master=None, **kw):
        inactivebg = kw.pop('inactivebackground', 'white')
        inactivefg = kw.pop('inactiveforeground', 'black')
        tk.Entry.__init__(self, master=master, **kw)
        supportinactive.__init__(self, inactivebg, inactivefg)

# Spinbox will have the same functionality too.
class Spinbox(tk.Spinbox, supportinactive):
    def __init__(self, master=None, **kw):
        inactivebg = kw.pop('inactivebackground', 'white')
        inactivefg = kw.pop('inactiveforeground', 'black')
        tk.Spinbox.__init__(self, master=master, **kw)
        supportinactive.__init__(self, inactivebg, inactivefg)

如果您想了解这种继承是如何工作的,请查看以下答案:-

【讨论】:

    【解决方案2】:

    我将发布作为答案,因此我可以添加图片并具体说明未更改的配置。 上面的答案是更改这些配置的一种非常好的方法,但仅在使用 tk.Entry() 小部件时才有效。我正在使用ttk.Entry()'clam' 主题。 'clam' 主题是在选择文本并且小部件失焦时为背景/前景引入此附加配置的主题。 上面给出的答案修改的是:

    • 失焦时未选择文本的背景/前景。

    我要修改的(去掉):

    • 使用 ttk.Entry 和 'clam' 时所选文本的背景/前景失焦。

    这里我在使用ttk.Entry()'clam' 作为主题时应用了上述答案。

    import tkinter as tk
    from tkinter import ttk
    
    root = tk.Tk()
    root.geometry('200x100')
    
    style = ttk.Style()
    style.theme_use('clam')
    style.configure('New.TEntry',
                    fieldbackground='red',
                    foreground='green',
                    selectbackground='black',
                    selectforeground='yellow')
    
    class NewEntry(ttk.Entry):
        def __init__(self, parent, style):
            super().__init__(parent)
            self.style = style
            self['style'] = 'New.TEntry'
    
            self.bind('<FocusIn>', self._focusin, '+')
            self.bind('<FocusOut>', self._focusout, '+')
    
        def _focusout(self, evt=None):
            self.style.configure('New.TEntry',
                                 fieldbackground='red',
                                 foreground='green',
                                 selectbackground='black',
                                 selectforeground='yellow')
    
        def _focusin(self, evt=None):
            self.style.configure('New.TEntry',
                                 fieldbackground='blue',
                                 foreground='pink',
                                 selectbackground='black',
                                 selectforeground='yellow')
    
    
    entry1 = NewEntry(root, style).pack()
    entry2 = tk.Entry(root).pack()
    
    root.mainloop()
    

    这是一个演练:

    • entry1 处于焦点位置,未选择任何文本。由fieldbackgroundforeground 设置的颜色属性。

    • entry1 处于焦点位置,一半的文本被选中。选定文本的颜色属性由selectbackgroundselectforeground 定义

    • entry1 失焦。光标在 entry2 中。仍然被选中的文本的颜色受我一些未知的属性支配。 selectbackgroundselectforeground 失焦仅对未选中的部分有效。

    当在其他地方选择新文本时 - 颜色将由 selectbackgroundselectforeground 定义为应有的颜色

    正如我在原始帖子中提到的,例如 tk.Text() 有一个选项 inactiveselectbackground。所以我相信在某个地方存在类似的东西。这只是一个如何访问该属性的问题。

    附: 这也让我想知道在课堂上修改style 的最简单方法是什么。我还没有看到有人这样做。我想在课堂上传递style 可以让我这样做。也许有更好的方法。

    【讨论】:

    • 好答案,但是如果您对多个条目使用“New.TEntry”样式名称,那么它可能会与不同的条目小部件发生冲突,最好为每个创建的实例使用唯一名称'NewEntry' 类的。您可以通过将“New.TEntry”替换为“%s.TEntry”%self 来解决此问题。
    猜你喜欢
    • 1970-01-01
    • 2012-03-22
    • 2021-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-14
    • 2017-07-28
    • 2017-06-10
    相关资源
    最近更新 更多