Skip to content

Commit af9e17b

Browse files
authored
set mpl style parameters from napari theme
1 parent 2778e1c commit af9e17b

File tree

2 files changed

+54
-24
lines changed

2 files changed

+54
-24
lines changed

src/napari_matplotlib/base.py

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import matplotlib
66
import matplotlib.style as mplstyle
77
import napari
8+
from napari.utils.theme import get_theme
89
from matplotlib.backends.backend_qtagg import ( # type: ignore[attr-defined]
910
FigureCanvasQTAgg,
1011
NavigationToolbar2QT,
@@ -13,7 +14,7 @@
1314
from qtpy.QtGui import QIcon
1415
from qtpy.QtWidgets import QLabel, QVBoxLayout, QWidget
1516

16-
from .util import Interval, from_napari_css_get_size_of
17+
from .util import Interval, from_napari_css_get_size_of, style_sheet_from_theme
1718

1819
__all__ = ["BaseNapariMPLWidget", "NapariMPLWidget", "SingleAxesWidget"]
1920

@@ -45,10 +46,11 @@ def __init__(
4546
):
4647
super().__init__(parent=parent)
4748
self.viewer = napari_viewer
48-
self._mpl_style_sheet_path: Optional[Path] = None
49+
#self._mpl_style_sheet_path: Optional[Path] = None
50+
self.napari_theme_style_sheet = style_sheet_from_theme(get_theme(napari_viewer.theme, as_dict=False))
4951

5052
# Sets figure.* style
51-
with mplstyle.context(self.mpl_style_sheet_path):
53+
with mplstyle.context(self.napari_theme_style_sheet):
5254
self.canvas = FigureCanvasQTAgg() # type: ignore[no-untyped-call]
5355

5456
self.canvas.figure.set_layout_engine("constrained")
@@ -68,23 +70,23 @@ def figure(self) -> Figure:
6870
"""Matplotlib figure."""
6971
return self.canvas.figure
7072

71-
@property
72-
def mpl_style_sheet_path(self) -> Path:
73-
"""
74-
Path to the set Matplotlib style sheet.
75-
"""
76-
if self._mpl_style_sheet_path is not None:
77-
return self._mpl_style_sheet_path
78-
elif (_CUSTOM_STYLE_PATH).exists():
79-
return _CUSTOM_STYLE_PATH
80-
elif self._napari_theme_has_light_bg():
81-
return Path(__file__).parent / "styles" / "light.mplstyle"
82-
else:
83-
return Path(__file__).parent / "styles" / "dark.mplstyle"
84-
85-
@mpl_style_sheet_path.setter
86-
def mpl_style_sheet_path(self, path: Path) -> None:
87-
self._mpl_style_sheet_path = Path(path)
73+
#@property
74+
#def mpl_style_sheet_path(self) -> Path:
75+
# """
76+
# Path to the set Matplotlib style sheet.
77+
# """
78+
# if self._mpl_style_sheet_path is not None:
79+
# return self._mpl_style_sheet_path
80+
# elif (_CUSTOM_STYLE_PATH).exists():
81+
# return _CUSTOM_STYLE_PATH
82+
# elif self._napari_theme_has_light_bg():
83+
# return Path(__file__).parent / "styles" / "light.mplstyle"
84+
# else:
85+
# return Path(__file__).parent / "styles" / "dark.mplstyle"
86+
87+
#@mpl_style_sheet_path.setter
88+
#def mpl_style_sheet_path(self, path: Path) -> None:
89+
# self._mpl_style_sheet_path = Path(path)
8890

8991
def add_single_axes(self) -> None:
9092
"""
@@ -94,13 +96,14 @@ def add_single_axes(self) -> None:
9496
"""
9597
# Sets axes.* style.
9698
# Does not set any text styling set by axes.* keys
97-
with mplstyle.context(self.mpl_style_sheet_path):
99+
with mplstyle.context(self.napari_theme_style_sheet):
98100
self.axes = self.figure.add_subplot()
99101

100102
def _on_napari_theme_changed(self) -> None:
101103
"""
102104
Called when the napari theme is changed.
103105
"""
106+
self.napari_theme_style_sheet = style_sheet_from_theme(get_theme(self.napari_viewer.theme, as_dict=False))
104107
self._replace_toolbar_icons()
105108

106109
def _napari_theme_has_light_bg(self) -> bool:
@@ -252,7 +255,7 @@ def _draw(self) -> None:
252255
"""
253256
# Clearing axes sets new defaults, so need to make sure style is applied when
254257
# this happens
255-
with mplstyle.context(self.mpl_style_sheet_path):
258+
with mplstyle.context(self.napari_theme_style_sheet):
256259
self.clear()
257260
if self.n_selected_layers in self.n_layers_input and all(
258261
isinstance(layer, self.input_layer_types) for layer in self.layers
@@ -300,7 +303,7 @@ def clear(self) -> None:
300303
"""
301304
Clear the axes.
302305
"""
303-
with mplstyle.context(self.mpl_style_sheet_path):
306+
with mplstyle.context(self.napari_theme_style_sheet):
304307
self.axes.clear()
305308

306309

src/napari_matplotlib/util.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
from typing import Optional, Union
1+
from typing import Dict, Optional, Union
22
from warnings import warn
33

44
import napari.qt
55
import tinycss2
6+
from napari.utils.theme import Theme
67
from qtpy.QtCore import QSize
78

89

@@ -138,3 +139,29 @@ def from_napari_css_get_size_of(
138139
RuntimeWarning,
139140
)
140141
return QSize(*fallback)
142+
143+
144+
def style_sheet_from_theme(theme: Theme) -> Dict[str, str]:
145+
return {
146+
'axes.edgecolor':theme.secondary.as_hex(),
147+
# alternatively "axes.facecolor" could be background color or not be set at all,
148+
# but this causes problems when saving figure as image
149+
'axes.facecolor':theme.canvas.as_hex(),
150+
'axes.labelcolor':theme.text.as_hex(),
151+
'boxplot.boxprops.color':theme.text.as_hex(),
152+
'boxplot.capprops.color':theme.text.as_hex(),
153+
'boxplot.flierprops.markeredgecolor':theme.text.as_hex(),
154+
'boxplot.whiskerprops.color':theme.text.as_hex(),
155+
'figure.edgecolor':theme.secondary.as_hex(),
156+
# alternatively "figure.facecolor" could not be set, but this causes problems
157+
# when saving figure as image
158+
'figure.facecolor':theme.background.as_hex(),
159+
'grid.color':theme.foreground.as_hex(),
160+
'legend.edgecolor':theme.secondary.as_hex(),
161+
'legend.facecolor':theme.background.as_hex(),
162+
'text.color':theme.text.as_hex(),
163+
'xtick.color':theme.secondary.as_hex(),
164+
'xtick.labelcolor':theme.text.as_hex(),
165+
'ytick.color':theme.secondary.as_hex(),
166+
'ytick.labelcolor':theme.text.as_hex(),
167+
}

0 commit comments

Comments
 (0)