From ba4262b2001e0a43764b60cda1d995e4daf9c002 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Sun, 29 Mar 2026 11:56:59 -0400 Subject: [PATCH 1/3] feat: add _GhostToolButton for improved toggle button appearance in QCollapsible --- src/superqt/collapsible/_collapsible.py | 41 +++++++++++++++++++++---- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/src/superqt/collapsible/_collapsible.py b/src/superqt/collapsible/_collapsible.py index a388f2fb..4fc30a55 100644 --- a/src/superqt/collapsible/_collapsible.py +++ b/src/superqt/collapsible/_collapsible.py @@ -13,8 +13,39 @@ Qt, Signal, ) -from qtpy.QtGui import QIcon, QPainter, QPalette, QPixmap -from qtpy.QtWidgets import QFrame, QPushButton, QSizePolicy, QVBoxLayout, QWidget +from qtpy.QtGui import QIcon, QPainter, QPaintEvent, QPalette, QPixmap +from qtpy.QtWidgets import ( + QFrame, + QSizePolicy, + QStyle, + QStyleOptionToolButton, + QStylePainter, + QToolButton, + QVBoxLayout, + QWidget, +) + + +class _GhostToolButton(QToolButton): + """Tool button that keeps a ghost appearance while checked.""" + + def __init__(self, parent: QWidget | None = None, *, title: str = "") -> None: + super().__init__(parent) + if title: + self.setText(title) + self.setCheckable(True) + self.setAutoRaise(True) + self.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon) + self.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) + + def paintEvent(self, a0: QPaintEvent | None) -> None: + if not a0: + return super().paintEvent(a0) + option = QStyleOptionToolButton() + self.initStyleOption(option) + option.state &= ~QStyle.StateFlag.State_On + painter = QStylePainter(self) + painter.drawControl(QStyle.ControlElement.CE_ToolButtonLabel, option) class QCollapsible(QFrame): @@ -39,13 +70,11 @@ def __init__( self._is_animating = False self._text = title - self._toggle_btn = QPushButton(title) - self._toggle_btn.setCheckable(True) + self._toggle_btn = _GhostToolButton(self, title=title) self.setCollapsedIcon(icon=collapsedIcon) self.setExpandedIcon(icon=expandedIcon) self.setSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Maximum) - self._toggle_btn.setStyleSheet("text-align: left; border: none; outline: none;") self._toggle_btn.toggled.connect(self._toggle) # frame layout @@ -68,7 +97,7 @@ def __init__( _content.layout().setContentsMargins(QMargins(5, 0, 0, 0)) self.setContent(_content) - def toggleButton(self) -> QPushButton: + def toggleButton(self) -> QToolButton: """Return the toggle button.""" return self._toggle_btn From 7e76116527d275096bb423e5ec93aca7cb8c1ebf Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Sun, 29 Mar 2026 12:08:49 -0400 Subject: [PATCH 2/3] fix: remove fixed size policy from _GhostToolButton for better layout flexibility --- src/superqt/collapsible/_collapsible.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/superqt/collapsible/_collapsible.py b/src/superqt/collapsible/_collapsible.py index 4fc30a55..2129a70f 100644 --- a/src/superqt/collapsible/_collapsible.py +++ b/src/superqt/collapsible/_collapsible.py @@ -36,7 +36,6 @@ def __init__(self, parent: QWidget | None = None, *, title: str = "") -> None: self.setCheckable(True) self.setAutoRaise(True) self.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon) - self.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) def paintEvent(self, a0: QPaintEvent | None) -> None: if not a0: From 08dd4c7d5b554bc6f4d7c0fda7cf4c9511b2b41a Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Sun, 29 Mar 2026 12:19:35 -0400 Subject: [PATCH 3/3] feat: match QPushButton typography for consistent header text size in _GhostToolButton --- src/superqt/collapsible/_collapsible.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/superqt/collapsible/_collapsible.py b/src/superqt/collapsible/_collapsible.py index 2129a70f..69a9c983 100644 --- a/src/superqt/collapsible/_collapsible.py +++ b/src/superqt/collapsible/_collapsible.py @@ -15,6 +15,7 @@ ) from qtpy.QtGui import QIcon, QPainter, QPaintEvent, QPalette, QPixmap from qtpy.QtWidgets import ( + QApplication, QFrame, QSizePolicy, QStyle, @@ -33,6 +34,8 @@ def __init__(self, parent: QWidget | None = None, *, title: str = "") -> None: super().__init__(parent) if title: self.setText(title) + # Match QPushButton typography from main for consistent header text size. + self.setFont(QApplication.font("QPushButton")) self.setCheckable(True) self.setAutoRaise(True) self.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)