我的最终解决方案是这样的:
所有关于色彩的行为被封装在按钮部件。
我使用处理程序控制事件,该处理程序使用较浅的颜色更改活动状态的背景颜色。
每当颜色改变时,它会通过我的函数完成,所以我用.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