tkinter - 为颜色选择器定义 "custom colors"

tkinter - define "custom colors" for colorchooser

我目前在项目中使用 tkinter 中的 colorchooser 来允许用户选择自定义颜色。至少,这可以通过

创建(在 Python 3.x 中)
from tkinter import colorchooser

cp = colorchooser.askcolor()

当这个 window 出现时(至少在 Windows 中),有一个名为 "Custom colors"

的部分

有什么方法可以用我选择的颜色预填充此部分?

不,无法从 tkinter 预填充自定义颜色。

你看到的是常见的Color dialog box, which is native Windows dialog. It's not possible to specify custom colors within tkinter, because they're handled at a lower level

天真的实现(使用 ctypes)可能是这样的:

import ctypes
import ctypes.wintypes as wtypes


class CHOOSECOLOR(ctypes.Structure):
    """" a class to represent CWPRETSTRUCT structure
    https://msdn.microsoft.com/en-us/library/windows/desktop/ms646830(v=vs.85).aspx """

    _fields_ = [('lStructSize', wtypes.DWORD),
                ('hwndOwner', wtypes.HWND),
                ('hInstance', wtypes.HWND),
                ('rgbResult', wtypes.COLORREF),
                ('lpCustColors', ctypes.POINTER(wtypes.COLORREF)),
                ('Flags', wtypes.DWORD),
                ('lCustData', wtypes.LPARAM),
                ('lpfnHook', wtypes.LPARAM),
                ('lpTemplateName', ctypes.c_char_p)]


class ColorChooser:
    """ a class to represent Color dialog box
    https://msdn.microsoft.com/en-gb/library/windows/desktop/ms646912(v=vs.85).aspx """
    CC_SOLIDCOLOR = 0x80
    CC_FULLOPEN = 0x02
    custom_color_array = ctypes.c_uint32 * 16
    color_chooser = ctypes.windll.Comdlg32.ChooseColorW

    def to_custom_color_array(self, custom_colors):
        custom_int_colors = self.custom_color_array()

        for i in range(16):
            custom_int_colors[i] = rgb_to_int(*custom_colors[i])

        return custom_int_colors

    def askcolor(self, custom_colors):
        struct = CHOOSECOLOR()

        ctypes.memset(ctypes.byref(struct), 0, ctypes.sizeof(struct))
        struct.lStructSize = ctypes.sizeof(struct)
        struct.Flags = self.CC_SOLIDCOLOR | self.CC_FULLOPEN
        struct.lpCustColors = self.to_custom_color_array(custom_colors)

        if self.color_chooser(ctypes.byref(struct)):
            result = int_to_rgb(struct.rgbResult)
        else:
            result = None

        return result


def rgb_to_int(red, green, blue):
    return red + (green << 8) + (blue << 16)


def int_to_rgb(int_color):
    red = int_color & 255
    green = (int_color >> 8) & 255
    blue = (int_color >> 16) & 255

    return red, green, blue

colors = [(250, 0, 0), (0, 250, 0), (0, 0, 250), (255, 255, 255)] * 4

chooser = ColorChooser()
result_color = chooser.askcolor(colors)
print(result_color)

请记住,还有扩展空间,例如,在调用之间保留自定义颜色数组并支持十六进制 colors/arbitrary 数组长度。