【问题标题】:Python: How to change the border color of ttk.Checkbutton when it is active?Python:如何在 ttk.Checkbutton 处于活动状态时更改它的边框颜色?
【发布时间】:2020-04-07 07:17:38
【问题描述】:

我想更改 ttk.Checkbutton 小部件的边框颜色,默认为浅蓝色。我尝试使用 ttk.Style() 的配置功能并设法在它处于活动状态时更改整个按钮或其他东西的颜色,但不是复选框的边框。 另一个问题是,我可以在哪里找到此类信息,例如可以在 ttk 样式中更改的所有选项的某种文档?

这是我尝试过的一个示例:

from tkinter import ttk

root = Tk()

s = ttk.Style()
s.configure('MyOwn.TCheckbutton',
    background='white',)
s.map('MyOwn.TCheckbutton',
       foreground=[('active', 'red')])

cb = ttk.Checkbutton(root,text='Text',style='MyOwn.TCheckbutton')
cb.pack()
root.mainloop()

当我将鼠标悬停在复选按钮上时,我可以更改文本的颜色,但我不知道如何更改复选框的边框颜色。

【问题讨论】:

  • 你能分享你尝试过的代码吗?
  • 当然,我在问题中添加了它。
  • @Tobias “我在问题中添加了它”:您没有显示您尝试更改 边框颜色检查按钮。此外,您的最后一句话:“如何更改复选框的边框颜色” 与您的问题标题相矛盾。 Edit您的问题并澄清。

标签: python tkinter ttk


【解决方案1】:

您的问题

我相信您遇到的问题是 Ttk Checkbutton 实际上不是一个绘制的小部件,而是一个图像。

如何发现?

如果有人查看 github 项目 ttkthemes 并查看 themes folder,然后转到 radiance folder(这是一个类似 UBUNTU 的主题),然后转到 to the folder inside that labelled "radiance"

你会看到这样的东西: 我们看到一个充满“GIF”的文件夹,这些是图像文件,如果向下滚动并找到文件:

check-dc.gif (Disabled Deselected)
check-du.gif (Disabled Deselected)
check-nc.gif (Normal Selected)
check-nu.gif (Normal Deselected)

如果我们查看这些文件可以看到,这些都是检查按钮的所有不同可能状态。

在 windows 下,这些检查按钮看起来像这样(生成 with this code):

如何包含自定义检查按钮?

可以在here 找到一篇关于此的精彩帖子,他们通过在画布上添加绿色和红色方块来创建自定义检查按钮,但如果有人想要制作与您想要的类似的东西怎么办。在哪里更改检查按钮的颜色。

如何更改默认检查按钮的边框颜色?

首先让我们将所有 Checkbutton 图像转换为 gif 格式,我已经为您完成了,可以从my Google Drive 或我的Gofile 下载。

您需要从我的 Google 云端硬盘中获取:

check-nc.gif (Normal Selected)
check-nu.gif (Normal Deselected)

因为您无需担心已停用的值,因为它们永远不会被聚焦。

现在让我们看看他们如何加载上述帖子中的图像:

on_image = tk.PhotoImage(width=48, height=24)
off_image = tk.PhotoImage(width=48, height=24)
on_image.put(("green",), to=(0, 0, 23,23))
off_image.put(("red",), to=(24, 0, 47, 23))

在这里他们创建了两个空白图像,它们是 48px X 24px,其中两个在左侧添加了一个绿色方块,另一个在右侧添加了一个。

我们的处理方法类似但略有不同,相反,我们将加载您下载的两个 gif 文件,然后我们将编写一个脚本来制作 4 个矩形,这些矩形将覆盖当前的灰色轮廓复选按钮。像这样:

import tkinter as tk

root = tk.Tk()

def edit_check(colour, image):
    image.put((colour,), to=(0, 0, 1, 13)) # LEFT
    image.put((colour,), to=(0, 0, 13, 1)) # TOP
    image.put((colour,), to=(12, 0, 13, 13)) # RIGHT
    image.put((colour,), to=(0, 12, 13, 13)) # BOTTOM

def focus_in(event):
    print(event)
    image = off_image if var1.get() == 0 else on_image
    edit_check("red", image)
    cb1.configure(image=image)
    cb1.image = image

def focus_out(event):
    print(event)
    image = off_image if var1.get() == 0 else on_image
    edit_check("black", image)
    cb1.configure(image=image)
    cb1.image = image

on_image = tk.PhotoImage(file="check-nc.gif") # Instead of creating a new image we open an existing one
off_image = tk.PhotoImage(file="check-nu.gif") # Instead of creating a new image we open an existing one

var1 = tk.IntVar(value=0)
cb1 = tk.Checkbutton(root, image=off_image, selectimage=on_image, indicatoron=False,
                     onvalue=1, offvalue=0, variable=var1, offrelief='sunken')
cb1.pack(padx=20, pady=10)

# THESE IF YOU WANT TRUE FOCUS
#cb1.bind("<FocusIn>", focus_in)
#cb1.bind("<FocusOut>", focus_out)

# THESE IF YOU WANT MOUSE OVER
cb1.bind("<Enter>", focus_in)
cb1.bind("<Leave>", focus_out)
root.mainloop()

使用面向对象编程改进代码

这对于您的用例来说是更好的系统(请注意,它不需要任何图像文件,因为文件保存为 base64 字符串)

import tkinter as tk

check_nu = b'iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAABhGlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV9TRZEWB4uIOGSoTi2IijpKFYtgobQVWnUwufQLmjQkKS6OgmvBwY/FqoOLs64OroIg+AHi4uqk6CIl/i8ptIjx4Lgf7+497t4BQqPCVLNrHFA1y0jFY2I2tyr2vCKAIAYRwYzETD2RXszAc3zdw8fXuyjP8j735wgqeZMBPpF4jumGRbxBPL1p6Zz3iUOsJCnE58QRgy5I/Mh12eU3zkWHBZ4ZMjKpeeIQsVjsYLmDWclQiaeIw4qqUb6QdVnhvMVZrdRY6578hYG8tpLmOs0RxLGEBJIQIaOGMiqwEKVVI8VEivZjHv5hx58kl0yuMhg5FlCFCsnxg//B727NwuSEmxSIAd0vtv0xCvTsAs26bX8f23bzBPA/A1da219tALOfpNfbWvgI6N8GLq7bmrwHXO4AQ0+6ZEiO5KcpFArA+xl9Uw4YuAX61tzeWvs4fQAy1NXyDXBwCIwVKXvd4929nb39e6bV3w/0UXLbKEvbjQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB+MMDRctIGmzOYIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAALElEQVQoz2M0Njb+z0AiYGFgYGA4c+YMI7EaTExM/jMxkAFGNQ1jTYzkpD0ATtMHS/nRiQwAAAAASUVORK5CYII='
check_nc = b'iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAABhGlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV9TRZEWB4uIOGSoTi2IijpKFYtgobQVWnUwufQLmjQkKS6OgmvBwY/FqoOLs64OroIg+AHi4uqk6CIl/i8ptIjx4Lgf7+497t4BQqPCVLNrHFA1y0jFY2I2tyr2vCKAIAYRwYzETD2RXszAc3zdw8fXuyjP8j735wgqeZMBPpF4jumGRbxBPL1p6Zz3iUOsJCnE58QRgy5I/Mh12eU3zkWHBZ4ZMjKpeeIQsVjsYLmDWclQiaeIw4qqUb6QdVnhvMVZrdRY6578hYG8tpLmOs0RxLGEBJIQIaOGMiqwEKVVI8VEivZjHv5hx58kl0yuMhg5FlCFCsnxg//B727NwuSEmxSIAd0vtv0xCvTsAs26bX8f23bzBPA/A1da219tALOfpNfbWvgI6N8GLq7bmrwHXO4AQ0+6ZEiO5KcpFArA+xl9Uw4YuAX61tzeWvs4fQAy1NXyDXBwCIwVKXvd4929nb39e6bV3w/0UXLbKEvbjQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB+MMDRctDrVlNE0AAAAjdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVAgd2l0aCBsb3ZlyGW0XgAAAJdJREFUKM+d0rENAyEMBdDvKA1zeART07MIGzAFE7EDK1B5CMqf7pIUlyP3JZdP+rItZkb8mScAjDFkF8QY+cCNbCF3R86ZvXduIXdHKYWqipSSXKJP0FqTEMK7Xu+dOWe6+yU4UEpJVBWlFLr7TwAAYmYcY8haC7VWzjkBAGfga+UhBLTWRFVPwREzI0nsjpndO67c+b0XBDxvkWRMW24AAAAASUVORK5CYII='


class example_window:
    def __init__(self, master):
        self.master = master
        chckbox = custom_checkbox(master, "red")
        chckbox.pack(padx=20, pady=10)
        

class custom_checkbox(tk.Checkbutton):
    def __init__(self, parent, colour, *args, **kwargs):
        default_kwargs = {'image': None, 'selectimage': None, 'indicatoron': False,
                          'onvalue': 1, 'offvalue': 0, 'variable': None, 'offrelief': 'sunken'}
        for key, value in default_kwargs.items():
            if key not in kwargs:
                kwargs[key] = value

        self.colour = colour
        self.curr_colour = "black"
        self.hover = False
        if kwargs['variable'] is None:
            self.variable = kwargs['variable'] = tk.IntVar(value=1)
        else:
            self.variable = kwargs['variable']
        print(kwargs, kwargs['variable'].get())
        if kwargs['variable'].get() == 0:
            if kwargs['image'] is None:
                self.off_image = kwargs['image'] = tk.PhotoImage(data=check_nu)
            else:
                self.off_image = kwargs['image']
            if kwargs['selectimage'] is None:
                self.on_image = tk.PhotoImage(data=check_nc)
            else:
                self.on_image = kwargs['selectimage']
        else:
            if kwargs['image'] is None:
                self.on_image = kwargs['image'] = tk.PhotoImage(data=check_nc)
            else:
                self.on_image = kwargs['image']
            if kwargs['selectimage'] is None:
                self.off_image = tk.PhotoImage(data=check_nu)
            else:
                self.off_image = kwargs['selectimage']

        tk.Checkbutton.__init__(self, parent, *args, **kwargs)
        self.bind("<Enter>", self.focus_in)
        self.bind("<Leave>", self.focus_out)
        self.variable.trace("w", self.focus_update)

    def edit_check(self, colour, image):
        image.put((colour,), to=(0, 0, 1, 13)) # LEFT
        image.put((colour,), to=(0, 0, 13, 1)) # TOP
        image.put((colour,), to=(12, 0, 13, 13)) # RIGHT
        image.put((colour,), to=(0, 12, 13, 13)) # BOTTOM

        
    def focus_in(self, event=None):
        image = self.on_image if self.variable.get() == self['onvalue'] else self.off_image
        self.edit_check(self.colour, image)
        self.curr_colour = self.colour
        self.configure(image=image)
        self.image = image
        self.hover = True

    def focus_out(self, event=None):
        image = self.on_image if self.variable.get() == self['onvalue'] else self.off_image
        self.edit_check("black", image)
        self.curr_colour = "black"
        self.configure(image=image)
        self.image = image
        self.hover = False

    def focus_update(self, *args):

        if self.variable.get() == self['onvalue']:
            image = self.on_image
        else:
            image = self.off_image
        self.configure(image=image)
        self.image = image
        if self.hover:
            self.focus_in()

def main():
    root = tk.Tk()
    example_window_gui = example_window(root)
    root.mainloop()

if __name__ == '__main__':
    main()

如果您希望能够向此小部件添加文本,请查看this code

【讨论】:

    【解决方案2】:

    【讨论】:

    • 谢谢,这有助于找到如何为 Checkbutton 的不同状态赋予不同的样式,但是您知道哪个参数会改变 Checkbox 的边框吗?
    • 在 ttk checkbutton 链接中,它说您需要使用样式来更新边框,因为这是 ttk checkbutton 不支持的参数。创建/编辑样式时的 .border 应该可以工作。或者切换到标准的 tk 检查按钮
    猜你喜欢
    • 2019-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-10
    • 1970-01-01
    • 1970-01-01
    • 2018-08-04
    相关资源
    最近更新 更多