Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2b03be1

Browse files
daniilStimhoffm
andcommitted
Change colour of Tk toolbar icons on dark backgrounds
Co-Authored-By: Tim Hoffmann <[email protected]>
1 parent eaadeb6 commit 2b03be1

File tree

2 files changed

+73
-2
lines changed

2 files changed

+73
-2
lines changed

lib/matplotlib/backends/_backend_tk.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,16 @@ def set_cursor(self, cursor):
634634
except tkinter.TclError:
635635
pass
636636

637+
def _is_dark(self, button, color):
638+
# `winfo_rgb` returns an (r, g, b) tuple in the range from 0 to 65535
639+
return max(button.winfo_rgb(button.cget(color))) < 65535 / 2
640+
641+
def _recolor_icon(self, image, color):
642+
image_data = np.asarray(image).copy()
643+
black_mask = (image_data[..., :3] == 0).all(axis=-1)
644+
image_data[black_mask, :3] = color
645+
return Image.fromarray(image_data, mode="RGBA")
646+
637647
def _set_image_for_button(self, button):
638648
"""
639649
Set the image for a button based on its pixel size.
@@ -653,8 +663,30 @@ def _set_image_for_button(self, button):
653663
with Image.open(path_large if (size > 24 and path_large.exists())
654664
else path_regular) as im:
655665
image = ImageTk.PhotoImage(im.resize((size, size)), master=self)
656-
button.configure(image=image, height='18p', width='18p')
657-
button._ntimage = image # Prevent garbage collection.
666+
button._ntimage = image
667+
668+
# create a version of the icon with the button's text color
669+
foreground = (255 / 65535) * np.array(
670+
button.winfo_rgb(button.cget("foreground")))
671+
im_alt = self._recolor_icon(im, foreground)
672+
image_alt = ImageTk.PhotoImage(
673+
im_alt.resize((size, size)), master=self)
674+
button._ntimage_alt = image_alt
675+
676+
if (self._is_dark(button, "background")):
677+
button.configure(image=image_alt)
678+
else:
679+
button.configure(image=image)
680+
if (
681+
isinstance(button, tk.Checkbutton)
682+
and button.cget("selectcolor") != ""
683+
):
684+
if (self._is_dark(button, "selectcolor")):
685+
button.configure(selectimage=image_alt)
686+
else:
687+
button.configure(selectimage=image)
688+
689+
button.configure(height='18p', width='18p')
658690

659691
def _Button(self, text, image_file, toggle, command):
660692
if not toggle:

lib/matplotlib/tests/test_backend_tk.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,42 @@ class Toolbar(NavigationToolbar2Tk):
185185
print("success")
186186
Toolbar(fig.canvas, fig.canvas.manager.window) # This should not raise.
187187
print("success")
188+
189+
190+
@pytest.mark.backend('TkAgg', skip_on_importerror=True)
191+
@_isolated_tk_test(success_count=2)
192+
def test_embedding(): # pragma: no cover
193+
import tkinter as tk
194+
from matplotlib.backends.backend_tkagg import (
195+
FigureCanvasTkAgg, NavigationToolbar2Tk)
196+
from matplotlib.backend_bases import key_press_handler
197+
from matplotlib.figure import Figure
198+
199+
root = tk.Tk()
200+
201+
def test_figure(master):
202+
fig = Figure()
203+
ax = fig.add_subplot()
204+
ax.plot([1, 2, 3])
205+
206+
canvas = FigureCanvasTkAgg(fig, master=master)
207+
canvas.draw()
208+
canvas.mpl_connect("key_press_event", key_press_handler)
209+
canvas.get_tk_widget().pack(expand=True, fill="both")
210+
211+
toolbar = NavigationToolbar2Tk(canvas, master, pack_toolbar=False)
212+
toolbar.pack(expand=True, fill="x")
213+
214+
canvas.get_tk_widget().forget()
215+
toolbar.forget()
216+
217+
test_figure(root)
218+
print("success")
219+
220+
# Test with a dark button color. Doesn't actually check whether the icon
221+
# color becomes lighter, just that the code doesn't break.
222+
223+
root.tk_setPalette(background="sky blue", selectColor="midnight blue",
224+
foreground="white")
225+
test_figure(root)
226+
print("success")

0 commit comments

Comments
 (0)