Closed antrrax closed 2 years ago
@antrrax, yes, I need to take a look at the colors for disabled buttons.
@antrrax
I found some code that I was able to modify for my own purpose. I can simulate a transparency effect that I think may be useful for many things in this application but specifically for this disabled color situation.
from PIL import Image, ImageColor
def make_transparent(alpha, foreground, background='#ffffff'):
"""Simulate color transparency.
Parameters:
alpha (float):
The amount of transparency; a number between 0 and 1.
foreground (str):
The foreground color.
background (str):
The background color.
Returns:
Tuple:
An rgb color representing the "transparent" version of the
foreground color against the background color.
"""
fg = ImageColor.getrgb(foreground)
bg = ImageColor.getrgb(background)
new = [alpha * c1 + (1 - alpha) * c2 for (c1, c2) in zip(fg, bg)]
return tuple([int(x) for x in new])
# testing
color1 = '#ff0000'
color2 = '#ffffff'
color3 = make_transparent(0.25, color1, color2)
img = Image.new('RGB', size=[100, 100], color=color3)
img.show()
color1
color2
color3
@antrrax @daniilS whare are you thoughts on using styled disabled buttons instead of using a standard gray color? Apparently there is a big debate on the topic (who knew).
I'm using 30% opacity on the light themes and 40% opacity on the dark themes in the example below
This is a scheme that could potentially be applied to all the widgets.
Also, having the new make_transparent
method will be super helpful in making the hover and focus color calculations much more consistent and as expected.
This contrast with transparency got much better.
If you need to determine if a color is light or dark you can use this formula: above 128 is considered light color
def get_color_luminosity(value):
"""
above 128 the color is considered light
below 128 the color is considered dark
Args:
value (tuple): RGB color tuple
"""
return int(((value[0] * 299) + (value[1] * 587) + (value[2] * 114)) / 1000)
Other Color Functions:
Maybe a calculation with tints will also help, see the 5th or 6th or 7th tint:
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import colorsys
import math
#https://www.color-hex.com/color/f44336
# Analogous Colors: -30º
# Triadic Colors: -120º
# Complementary Color: -180*
# Shades: color to 000000
# Tints: color to ffffff
####################################################
# SHADES
####################################################
def calc_shades(Percent, color_item):
return math.floor( (color_item) * ( (100-Percent) * 0.01 ) )
def get_ten_shades(tp_rgb_color):
rgb_shades = []
hex_shades = []
#variações de cor de 10% em 10%
for j in range(0, 110, 10):
r = calc_shades(j, tp_rgb_color[0])
g = calc_shades(j, tp_rgb_color[1])
b = calc_shades(j, tp_rgb_color[2])
new_rgb_tint = (r,g,b)
rgb_shades.append(new_rgb_tint)
new_hex_tint = rgb_to_hex(new_rgb_tint)
hex_shades.append(new_hex_tint)
return rgb_shades, hex_shades
####################################################
####################################################
# TINTS
####################################################
def calc_tints(Percent, color_item):
return math.floor( (color_item) + ( (255 - color_item) * ((100-Percent) * 0.01) ) )
def get_ten_tints(tp_rgb_color):
rgb_tints = []
hex_tints = []
#variações de cor de 10% em 10%
for j in range(100, -10, -10):
r = calc_tints(j, tp_rgb_color[0])
g = calc_tints(j, tp_rgb_color[1])
b = calc_tints(j, tp_rgb_color[2])
new_rgb_tint = (r,g,b)
rgb_tints.append(new_rgb_tint)
new_hex_tint = rgb_to_hex(new_rgb_tint)
hex_tints.append(new_hex_tint)
return rgb_tints, hex_tints
####################################################
####################################################
# ADJACENTS
####################################################
DEG30 = -30/360. #Analogous Colors
DEG120 = -120/360. #Triadic Colors
DEG180 = -180/360. #Complementary Color
def adjacent_colors(r, g, b, d=DEG30): # Assumption: r, g, b in [0, 255]
r, g, b = map(lambda x: x/255., [r, g, b]) # Convert to [0, 1]
h, l, s = colorsys.rgb_to_hls(r, g, b) # RGB -> HLS
h = [(h+d) % 1 for d in (-d, d)] # Rotation by d
adjacent = [map(lambda x: int(round(x*255)), colorsys.hls_to_rgb(hi, l, s))
for hi in h] # H'LS -> new RGB
return adjacent
####################################################
####################################################
# LUMINOSITY
####################################################
def get_color_luminosity(value):
"""
above 128 the color is considered light
below 128 the color is considered dark
Args:
value (tuple): RGB color tuple
"""
return int(((value[0] * 299) + (value[1] * 587) + (value[2] * 114)) / 1000)
####################################################
def rgb_to_hex(colortuple):
return '#' + ''.join(f'{i:02X}' for i in colortuple)
def hex_to_rgb(value):
value = value.lstrip('#')
lv = len(value)
return tuple(int(value[i:i+lv//3], 16) for i in range(0, lv, lv//3))
#--------- Example:
c_hex = '#f44336'
c_rgb = hex_to_rgb(c_hex)
print(c_hex, c_rgb)
print('\nluminosity:', get_color_luminosity(c_rgb), '\n')
analogous = adjacent_colors(c_rgb[0], c_rgb[1], c_rgb[2], d=DEG30)
for item in analogous:
print('Analogous:', tuple(item))
print('')
triadic = adjacent_colors(c_rgb[0], c_rgb[1], c_rgb[2], d=DEG120)
for item in triadic:
print('Triadic:' , tuple(item))
print('')
complementary = adjacent_colors(c_rgb[0], c_rgb[1], c_rgb[2], d=DEG180)
for item in complementary:
print('Complementary:' , tuple(item))
print('')
print('10 Tints:\n', get_ten_tints(c_rgb), '\n')
print('10 Shaders:\n', get_ten_shades(c_rgb))
alternatively, if I stick with the grayish disabled color, using a 12% transparency on the fg color and a 38% transparency on the background color gives me this result for dark and light themes.
I've found that the 'colored' disabled doesn't translate well to all the widgets. So perhaps a simple gray-ish color will work? Not decided yet.
In my opinion this second option with grayscale is better. As it is the default normally used in OS. It's easier for the user to understand
I also think the second option is more intuitive. If you do want to have a difference between colours, I would significantly reduce the saturation in the disabled state.
@antrrax, let me know if these updates fixed your issue. I believe they did, but would be nice to double-check.
It has improved a lot. Thanks
In light themes the disabled buttons are 'invisible'. ttkbootstrap 1.3.1
I'm starting the app with this setting:
https://www.mediafire.com/file/w33t3rzfdn318wa/disabled_buttons_no_contrast.mp4/file see the video, in dark themes there is a contrast of colors between the normal and disabled buttons. But in light themes there could be this contrast as well. Mainly on buttons without text that have a white image.
disabled buttons - light theme -- invisible, mostly buttons just white images.
default buttons - light theme -- OK
disabled buttons - dark theme -- OK
default buttons - dark theme -- OK
Am I doing something wrong?