mirror of
https://github.com/bec-project/bec_widgets.git
synced 2025-07-14 11:41:49 +02:00
WIP EXPANSION PANEL: Color works correct with qcolor and hex
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
import sys
|
||||
|
||||
from qtpy.QtCore import QEvent, Qt
|
||||
from qtpy.QtGui import QColor
|
||||
from qtpy.QtWidgets import (
|
||||
QWidget,
|
||||
QVBoxLayout,
|
||||
@ -18,10 +19,12 @@ from bec_widgets.utils.bec_widget import BECWidget
|
||||
|
||||
class ExpansionPanel(BECWidget, QWidget):
|
||||
"""
|
||||
A collapsible container widget for use in Qt Designer.
|
||||
This version avoids the traceback by deferring eventFilter installation
|
||||
until after header_frame and content_frame exist, and by checking they're
|
||||
not None before referencing them.
|
||||
A collapsible container widget for Qt Designer.
|
||||
|
||||
Key improvements in this version:
|
||||
- A "title_color" property (type "QColor") that accepts either
|
||||
a QColor or a string (hex/rgb/named color).
|
||||
- The label text color is updated accordingly.
|
||||
"""
|
||||
|
||||
PLUGIN = True
|
||||
@ -46,24 +49,23 @@ class ExpansionPanel(BECWidget, QWidget):
|
||||
|
||||
# Properties
|
||||
self._expanded = expanded
|
||||
self._title_color = QColor("black") # Default text color
|
||||
self.header_frame = None
|
||||
self.content_frame = None
|
||||
|
||||
# Setup the main layout
|
||||
# Main layout
|
||||
self._main_layout = QVBoxLayout(self)
|
||||
self._main_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self._main_layout.setSpacing(0)
|
||||
|
||||
# Create the header
|
||||
# Create header / content
|
||||
self._init_header(title)
|
||||
|
||||
# Create the content
|
||||
self._init_content()
|
||||
|
||||
# Make sure the content is initially visible or hidden
|
||||
# Visible or hidden
|
||||
self.content_frame.setVisible(expanded)
|
||||
|
||||
# Defer installing the event filter until everything is ready
|
||||
# Defer event filter after constructing frames
|
||||
self.installEventFilter(self)
|
||||
|
||||
def _init_header(self, title):
|
||||
@ -100,19 +102,10 @@ class ExpansionPanel(BECWidget, QWidget):
|
||||
self._main_layout.addWidget(self.header_frame)
|
||||
|
||||
def _init_content(self):
|
||||
"""
|
||||
Create the collapsible content frame, with its own QVBoxLayout.
|
||||
"""
|
||||
"""Create the collapsible content frame (with its own layout)."""
|
||||
self.content_frame = QFrame(self)
|
||||
self.content_frame.setObjectName("ContentFrame")
|
||||
self.content_frame.setStyleSheet(
|
||||
"""
|
||||
#ContentFrame {
|
||||
border: 1px solid #C0C0C0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
self.content_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
|
||||
self._content_layout = QVBoxLayout(self.content_frame)
|
||||
self._content_layout.setContentsMargins(5, 5, 5, 5)
|
||||
@ -139,7 +132,10 @@ class ExpansionPanel(BECWidget, QWidget):
|
||||
|
||||
@SafeProperty(str)
|
||||
def title(self):
|
||||
return self.label_title.text() if self.label_title else ""
|
||||
"""Property for the header text."""
|
||||
if self.label_title:
|
||||
return self.label_title.text()
|
||||
return ""
|
||||
|
||||
@title.setter
|
||||
def title(self, value: str):
|
||||
@ -147,33 +143,50 @@ class ExpansionPanel(BECWidget, QWidget):
|
||||
self.label_title.setText(value)
|
||||
|
||||
@SafeProperty("QColor")
|
||||
def label_color(self):
|
||||
return self.label_title.palette().color(self.label_title.foregroundRole())
|
||||
def title_color(self):
|
||||
"""
|
||||
A 'QColor' property recognized by Designer. We also accept
|
||||
strings for convenience (e.g. "#FF0000", "rgb(0,255,0)", "blue").
|
||||
"""
|
||||
return self._title_color
|
||||
|
||||
@label_color.setter
|
||||
def label_color(self, color):
|
||||
self.label_title.setStyleSheet(f"color: {color};")
|
||||
@title_color.setter
|
||||
def title_color(self, color):
|
||||
# TODO set bec widget color validator here
|
||||
|
||||
# If user passes a string instead of a QColor, parse it
|
||||
if isinstance(color, str):
|
||||
new_col = QColor(color)
|
||||
if not new_col.isValid():
|
||||
return # ignore invalid color string
|
||||
self._title_color = new_col
|
||||
elif isinstance(color, QColor):
|
||||
self._title_color = color
|
||||
else:
|
||||
# unknown type, ignore
|
||||
return
|
||||
|
||||
# Update label's style
|
||||
color_hex = self._title_color.name() # e.g. "#RRGGBB"
|
||||
self.label_title.setStyleSheet(f"color: {color_hex};")
|
||||
|
||||
@property
|
||||
def content_layout(self) -> QVBoxLayout:
|
||||
"""Return the layout of the content frame for programmatic additions."""
|
||||
"""Layout of the content frame for programmatic additions."""
|
||||
return self._content_layout
|
||||
|
||||
def event(self, e):
|
||||
"""
|
||||
Override event() to detect when child widgets are added by Designer,
|
||||
so we can place them into the content layout if they are not the header frame
|
||||
or content frame themselves.
|
||||
If Designer adds child widgets, re-parent them into _content_layout
|
||||
unless they're our known frames.
|
||||
"""
|
||||
if e.type() == QEvent.ChildAdded:
|
||||
child_obj = e.child()
|
||||
# Only process if we have a valid child widget
|
||||
if child_obj is not None and isinstance(child_obj, QWidget):
|
||||
# Also check if we have valid references to header_frame & content_frame
|
||||
if self.header_frame is not None and self.content_frame is not None:
|
||||
# If it's not our known frames, place it inside the content layout
|
||||
if child_obj not in (self.header_frame, self.content_frame):
|
||||
self._content_layout.addWidget(child_obj)
|
||||
|
||||
return super().event(e)
|
||||
|
||||
|
||||
@ -183,13 +196,22 @@ if __name__ == "__main__":
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
panel = ExpansionPanel(title="Test Panel", expanded=True)
|
||||
panel = ExpansionPanel(title="Test Panel", expanded=False)
|
||||
panel2 = ExpansionPanel(title="Test Panel 2", expanded=False)
|
||||
|
||||
# You can set the color via hex string
|
||||
panel.title_color = "#FF00FF"
|
||||
|
||||
panel.content_layout.addWidget(QPushButton("Test Button 1"))
|
||||
panel.content_layout.addWidget(QPushButton("Test Button 2"))
|
||||
|
||||
panel2.content_layout.addWidget(QPushButton("Test Button 1"))
|
||||
panel2.content_layout.addWidget(QPushButton("Test Button 2"))
|
||||
|
||||
container = QWidget()
|
||||
lay = QVBoxLayout(container)
|
||||
lay.addWidget(panel)
|
||||
lay.addWidget(panel2)
|
||||
container.resize(400, 300)
|
||||
container.show()
|
||||
|
||||
|
Reference in New Issue
Block a user