我的最終解決方案是這樣的:
所有關於色彩的行爲被封裝在按鈕部件。
我使用處理程序控制事件,該處理程序使用較淺的顏色更改活動狀態的背景顏色。
每當顏色改變時,它會通過我的函數完成,所以我用.generate_event()觸發''事件,更改顏色並解除當前處理程序的高亮顯示,然後綁定一個新處理程序以突出顯示替換前者。
我做了一個附配,樣式相關的方法和功能可重複使用的模塊:
styleUtils
import tkinter as tk
import tkinter.ttk as ttk
import random as rnd
style = None
def random_color():
"""
Returns a random color as a string
:return: a color
"""
def r():
return rnd.randint(0, 0xffff)
return '#{:04x}{:04x}{:04x}'.format(r(), r(), r())
def get_style(master=None):
"""
Returns the style object instance for handling styles
:param master: the parent component
:return: the style
"""
global style
if not style:
style = ttk.Style(master) if master else ttk.Style()
return style
def get_style_name(widget):
"""
Returns the the name of the current style applied on this widget
:param widget: the widget
:return: the name of the style
"""
# .config('style') call returns the tuple
# (option name, dbName, dbClass, default value, current value)
return widget.config('style')[-1]
def get_background_color(widget):
"""
Returns a string representing the background color of the widget
:param widget: a widget
:return: the color of the widget
"""
global style
color = style.lookup(get_style_name(widget), 'background')
return color
def highlighted_rgb(color_value):
"""
Returns a slightly modified rgb value
:param color_value: one of three possible rgb values
:return: one of three possible rgb values, but highlighted
"""
result = (color_value/65535) * 255
result += (255 - result)/2
return result
def highlighted_color(widget, color):
"""
Returns a highlighted color from the original entered
:param color: a color
:return: a highlight color for the one entered
"""
c = widget.winfo_rgb(color)
r = highlighted_rgb(c[0])
g = highlighted_rgb(c[1])
b = highlighted_rgb(c[2])
return ("#%2.2x%2.2x%2.2x" % (round(r), round(g), round(b))).upper()
def change_highlight_style(event=None):
"""
Applies the highlight style for a color
:param event: the event of the styled widget
"""
global style
widget = event.widget
current_color = get_background_color(widget)
color = highlighted_color(event.widget, current_color)
style.map(get_style_name(widget), background=[('active', color)])
可能需要改變調用代碼一點點去除現在不需要的代碼,但是這會馬上工作。
小工具。PY(對於按鈕的代碼)
import os
import tkinter as tk
import tkinter.ttk as ttk
from PIL.ImageTk import PhotoImage
from user.myProject.view import styleUtils
class ImgButton(ttk.Button):
"""
This has all the behaviour for a button which has an image
"""
def __init__(self, master=None, **kw):
super().__init__(master, **kw)
self._img = kw.get('image')
# TODO Replace this temporal test handler for testing highlight color
self.bind('<Button-1>', self.change_color)
def change_color(self, __=None):
"""
Changes the color of this widget randomly
:param __: the event, which is no needed
"""
import random as rnd
#Without this, nothing applies until the mouse leaves the widget
self.event_generate('<Leave>')
self.set_background_color(rnd.choice(['black', 'white', 'red', 'blue',
'cyan', 'purple', 'green', 'brown',
'gray', 'yellow', 'orange', 'cyan',
'pink', 'purple', 'violet']))
self.event_generate('<Enter>')
def get_style_name(self):
"""
Returns the specific style name applied for this widget
:return: the style name as a string
"""
return styleUtils.get_style_name(self)
def set_background_color(self, color):
"""
Sets this widget's background color to that received as parameter
:param color: the color to be set
"""
styleUtils.get_style().configure(self.get_style_name(), background=color)
# If the color changes we don't want the current handler for the old color anymore
self.unbind('<Enter>')
# We replace the handler for the new color
self.bind('<Enter>', self.change_highlight_style)
def get_background_color(self):
"""
Returns a string representing the background color of the widget
:return: the color of the widget
"""
return styleUtils.get_style().lookup(self.get_style_name(), 'background')
def change_highlight_style(self, __=None):
"""
Applies the highlight style for a color
:param __: the event, which is no needed
"""
current_color = self.get_background_color()
# We get the highlight lighter color for the current color and set it for the 'active' state
color = styleUtils.highlighted_color(self, current_color)
styleUtils.get_style().map(self.get_style_name(), background=[('active', color)])
調用代碼
import tkinter as tk
import tkinter.ttk as ttk
from widgets import ImgButton
class DiceFrame(ttk.Frame):
def __init__(self, master, *args, **kwargs):
super().__init__(master, *args, **kwargs)
current_style = 'Die.TButton'
style = ttk.Style()
style.configure(current_style,
borderwidth=6,
)
button = ImgButton(master, style=current_style)
button.pack(side=tk.LEFT)
if __name__ == "__main__":
root = tk.Tk()
DiceFrame(root).pack(side="top", fill="both", expand=True)
root.mainloop()
對不起。我添加了一些進口和一堂課,但我現在必須走了。我將在稍後完成源代碼。 – madtyn
@ j_4321剛剛完成 – madtyn