1
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2025-12-30 18:51:19 +01:00

fix: remove pyqtgraph styling logic

This commit is contained in:
2025-08-25 16:59:11 +02:00
parent a0e190e38d
commit 706490247b
5 changed files with 25 additions and 118 deletions

View File

@@ -80,8 +80,8 @@ class BECWidget(BECConnector):
def _connect_to_theme_change(self):
"""Connect to the theme change signal."""
qapp = QApplication.instance()
if hasattr(qapp, "theme_signal"):
qapp.theme_signal.theme_updated.connect(self._update_theme)
if hasattr(qapp, "theme"):
qapp.theme.theme_changed.connect(self._update_theme)
def _update_theme(self, theme: str | None = None):
"""Update the theme."""

View File

@@ -40,72 +40,9 @@ def get_accent_colors() -> AccentColors | None:
def apply_theme(theme: Literal["dark", "light"]):
"""
Apply the theme to all pyqtgraph widgets. Do not use this function directly. Use set_theme instead.
Apply the theme via the global theming API. This updates QSS, QPalette, and pyqtgraph globally.
"""
app = QApplication.instance()
graphic_layouts = [
child
for top in app.topLevelWidgets()
for child in top.findChildren(pg.GraphicsLayoutWidget)
]
plot_items = [
item
for gl in graphic_layouts
for item in gl.ci.items.keys() # ci is internal pg.GraphicsLayout that hosts all items
if isinstance(item, pg.PlotItem)
]
histograms = [
item
for gl in graphic_layouts
for item in gl.ci.items.keys() # ci is internal pg.GraphicsLayout that hosts all items
if isinstance(item, pg.HistogramLUTItem)
]
# Update background color based on the theme
if theme == "light":
background_color = "#e9ecef" # Subtle contrast for light mode
foreground_color = "#141414"
label_color = "#000000"
axis_color = "#666666"
else:
background_color = "#141414" # Dark mode
foreground_color = "#e9ecef"
label_color = "#FFFFFF"
axis_color = "#CCCCCC"
# update GraphicsLayoutWidget
pg.setConfigOptions(foreground=foreground_color, background=background_color)
for pg_widget in graphic_layouts:
pg_widget.setBackground(background_color)
# update PlotItems
for plot_item in plot_items:
for axis in ["left", "right", "top", "bottom"]:
plot_item.getAxis(axis).setPen(pg.mkPen(color=axis_color))
plot_item.getAxis(axis).setTextPen(pg.mkPen(color=label_color))
# Change title color
plot_item.titleLabel.setText(plot_item.titleLabel.text, color=label_color)
# Change legend color
if hasattr(plot_item, "legend") and plot_item.legend is not None:
plot_item.legend.setLabelTextColor(label_color)
# if legend is in plot item and theme is changed, has to be like that because of pg opt logic
for sample, label in plot_item.legend.items:
label_text = label.text
label.setText(label_text, color=label_color)
# update HistogramLUTItem
for histogram in histograms:
histogram.axis.setPen(pg.mkPen(color=axis_color))
histogram.axis.setTextPen(pg.mkPen(color=label_color))
# now define stylesheet according to theme and apply it
apply_theme_global(theme) # TODO for now this is patch
# style = bec_qthemes.load_stylesheet(theme)
# app.setStyleSheet(style)
apply_theme_global(theme)
class Colors:

View File

@@ -1,11 +1,12 @@
import pyqtgraph as pg
from qtpy.QtCore import Property
from qtpy.QtCore import Property, Qt
from qtpy.QtWidgets import QApplication, QFrame, QHBoxLayout, QVBoxLayout, QWidget
from bec_widgets.widgets.utility.visual.dark_mode_button.dark_mode_button import DarkModeButton
class RoundedFrame(QFrame):
# TODO this should be removed completely in favor of QSS styling, no time now
"""
A custom QFrame with rounded corners and optional theme updates.
The frame can contain any QWidget, however it is mainly designed to wrap PlotWidgets to provide a consistent look and feel with other BEC Widgets.
@@ -28,6 +29,9 @@ class RoundedFrame(QFrame):
self.setProperty("skip_settings", True)
self.setObjectName("roundedFrame")
# Ensure QSS can paint background/border on this widget
self.setAttribute(Qt.WA_StyledBackground, True)
# Create a layout for the frame
if orientation == "vertical":
self.layout = QVBoxLayout(self)
@@ -45,22 +49,10 @@ class RoundedFrame(QFrame):
# Automatically apply initial styles to the GraphicalLayoutWidget if applicable
self.apply_plot_widget_style()
self.update_style()
def apply_theme(self, theme: str):
"""
Apply the theme to the frame and its content if theme updates are enabled.
"""
if self.content_widget is not None and isinstance(
self.content_widget, pg.GraphicsLayoutWidget
):
self.content_widget.setBackground(self.background_color)
# Update background color based on the theme
if theme == "light":
self.background_color = "#e9ecef" # Subtle contrast for light mode
else:
self.background_color = "#141414" # Dark mode
"""Deprecated: RoundedFrame no longer handles theme; styling is QSS-driven."""
self.update_style()
@Property(int)
@@ -77,34 +69,21 @@ class RoundedFrame(QFrame):
"""
Update the style of the frame based on the background color.
"""
if self.background_color:
self.setStyleSheet(
f"""
self.setStyleSheet(
f"""
QFrame#roundedFrame {{
background-color: {self.background_color};
border-radius: {self._radius}; /* Rounded corners */
border-radius: {self._radius}px;
}}
"""
)
)
self.apply_plot_widget_style()
def apply_plot_widget_style(self, border: str = "none"):
"""
Automatically apply background, border, and axis styles to the PlotWidget.
Args:
border (str): Border style (e.g., 'none', '1px solid red').
Let QSS/pyqtgraph handle plot styling; avoid overriding here.
"""
if isinstance(self.content_widget, pg.GraphicsLayoutWidget):
# Apply border style via stylesheet
self.content_widget.setStyleSheet(
f"""
GraphicsLayoutWidget {{
border: {border}; /* Explicitly set the border */
}}
"""
)
self.content_widget.setBackground(self.background_color)
self.content_widget.setStyleSheet("")
class ExampleApp(QWidget): # pragma: no cover
@@ -128,24 +107,14 @@ class ExampleApp(QWidget): # pragma: no cover
plot_item_2.plot([1, 2, 4, 8, 16, 32], pen="r")
plot2.plot_item = plot_item_2
# Wrap PlotWidgets in RoundedFrame
rounded_plot1 = RoundedFrame(parent=self, content_widget=plot1)
rounded_plot2 = RoundedFrame(parent=self, content_widget=plot2)
# Add to layout
# Add to layout (no RoundedFrame wrapper; QSS styles plots)
layout.addWidget(dark_button)
layout.addWidget(rounded_plot1)
layout.addWidget(rounded_plot2)
layout.addWidget(plot1)
layout.addWidget(plot2)
self.setLayout(layout)
from qtpy.QtCore import QTimer
def change_theme():
rounded_plot1.apply_theme("light")
rounded_plot2.apply_theme("dark")
QTimer.singleShot(100, change_theme)
# Theme flip demo removed; global theming applies automatically
if __name__ == "__main__": # pragma: no cover

View File

@@ -135,7 +135,7 @@ class PlotBase(BECWidget, QWidget):
self._init_ui()
self._connect_to_theme_change()
self._update_theme()
self._update_theme(None)
def apply_theme(self, theme: str):
self.round_plot_widget.apply_theme(theme)
@@ -143,6 +143,8 @@ class PlotBase(BECWidget, QWidget):
def _init_ui(self):
self.layout.addWidget(self.layout_manager)
self.round_plot_widget = RoundedFrame(parent=self, content_widget=self.plot_widget)
self.round_plot_widget.setProperty("variant", "plot_background")
self.round_plot_widget.setProperty("frameless", True)
self.layout_manager.add_widget(self.round_plot_widget)
self.layout_manager.add_widget_relative(self.fps_label, self.round_plot_widget, "top")

View File

@@ -3,12 +3,11 @@ from __future__ import annotations
import json
from typing import TYPE_CHECKING
from qtpy.QtWidgets import QApplication
from bec_lib.logger import bec_logger
from bec_qthemes._icon.material_icons import material_icon
from qtpy.QtCore import Qt
from qtpy.QtWidgets import (
QApplication,
QComboBox,
QHBoxLayout,
QHeaderView,