gui.utils.dropdown_button
1from PySide6.QtWidgets import QPushButton, QMenu 2from PySide6.QtCore import Signal 3 4 5class DropdownButton(QPushButton): 6 """ 7 Reemplaza QComboBox con la estética del selector de curso: 8 botón con flecha ▾ que abre un QMenu estilizado con el tema activo. 9 10 API compatible con QComboBox: 11 addItem(text, userData=None) 12 addItems(texts) 13 currentText() / currentData() / currentIndex() 14 setCurrentIndex(idx) / setCurrentText(text) 15 count() / itemData(idx) 16 Signal currentIndexChanged(int) 17 """ 18 19 currentIndexChanged = Signal(int) 20 21 def __init__(self, parent=None): 22 super().__init__(parent) 23 self.setObjectName('dropdown_btn') 24 self._items: list[tuple[str, object]] = [] 25 self._current: int = -1 26 self.clicked.connect(self._show_menu) 27 28 # ── Construcción de ítems ───────────────────────────────────────────────── 29 30 def addItem(self, text: str, userData=None) -> None: 31 self._items.append((text, userData)) 32 if self._current == -1: 33 self._apply(0, emit=False) 34 35 def addItems(self, texts) -> None: 36 for t in texts: 37 self.addItem(t) 38 39 # ── Consulta ────────────────────────────────────────────────────────────── 40 41 def currentText(self) -> str: 42 if 0 <= self._current < len(self._items): 43 return self._items[self._current][0] 44 return '' 45 46 def currentData(self): 47 if 0 <= self._current < len(self._items): 48 return self._items[self._current][1] 49 return None 50 51 def currentIndex(self) -> int: 52 return self._current 53 54 def count(self) -> int: 55 return len(self._items) 56 57 def itemData(self, idx: int): 58 if 0 <= idx < len(self._items): 59 return self._items[idx][1] 60 return None 61 62 # ── Selección ───────────────────────────────────────────────────────────── 63 64 def setCurrentIndex(self, idx: int) -> None: 65 if 0 <= idx < len(self._items): 66 self._apply(idx) 67 68 def setCurrentText(self, text: str) -> None: 69 for i, (label, _) in enumerate(self._items): 70 if label == text: 71 self._apply(i) 72 return 73 74 # ── Internos ────────────────────────────────────────────────────────────── 75 76 def _apply(self, idx: int, emit: bool = True) -> None: 77 if idx == self._current: 78 return 79 self._current = idx 80 self.setText(f'{self.currentText()} ▾') 81 if emit: 82 self.currentIndexChanged.emit(idx) 83 84 def _show_menu(self) -> None: 85 menu = QMenu(self) 86 for i, (label, _) in enumerate(self._items): 87 act = menu.addAction(label) 88 act.setData(i) 89 if i == self._current: 90 act.setCheckable(True) 91 act.setChecked(True) 92 chosen = menu.exec(self.mapToGlobal(self.rect().bottomLeft())) 93 if chosen is not None: 94 self._apply(chosen.data())
class
DropdownButton(PySide6.QtWidgets.QPushButton):
6class DropdownButton(QPushButton): 7 """ 8 Reemplaza QComboBox con la estética del selector de curso: 9 botón con flecha ▾ que abre un QMenu estilizado con el tema activo. 10 11 API compatible con QComboBox: 12 addItem(text, userData=None) 13 addItems(texts) 14 currentText() / currentData() / currentIndex() 15 setCurrentIndex(idx) / setCurrentText(text) 16 count() / itemData(idx) 17 Signal currentIndexChanged(int) 18 """ 19 20 currentIndexChanged = Signal(int) 21 22 def __init__(self, parent=None): 23 super().__init__(parent) 24 self.setObjectName('dropdown_btn') 25 self._items: list[tuple[str, object]] = [] 26 self._current: int = -1 27 self.clicked.connect(self._show_menu) 28 29 # ── Construcción de ítems ───────────────────────────────────────────────── 30 31 def addItem(self, text: str, userData=None) -> None: 32 self._items.append((text, userData)) 33 if self._current == -1: 34 self._apply(0, emit=False) 35 36 def addItems(self, texts) -> None: 37 for t in texts: 38 self.addItem(t) 39 40 # ── Consulta ────────────────────────────────────────────────────────────── 41 42 def currentText(self) -> str: 43 if 0 <= self._current < len(self._items): 44 return self._items[self._current][0] 45 return '' 46 47 def currentData(self): 48 if 0 <= self._current < len(self._items): 49 return self._items[self._current][1] 50 return None 51 52 def currentIndex(self) -> int: 53 return self._current 54 55 def count(self) -> int: 56 return len(self._items) 57 58 def itemData(self, idx: int): 59 if 0 <= idx < len(self._items): 60 return self._items[idx][1] 61 return None 62 63 # ── Selección ───────────────────────────────────────────────────────────── 64 65 def setCurrentIndex(self, idx: int) -> None: 66 if 0 <= idx < len(self._items): 67 self._apply(idx) 68 69 def setCurrentText(self, text: str) -> None: 70 for i, (label, _) in enumerate(self._items): 71 if label == text: 72 self._apply(i) 73 return 74 75 # ── Internos ────────────────────────────────────────────────────────────── 76 77 def _apply(self, idx: int, emit: bool = True) -> None: 78 if idx == self._current: 79 return 80 self._current = idx 81 self.setText(f'{self.currentText()} ▾') 82 if emit: 83 self.currentIndexChanged.emit(idx) 84 85 def _show_menu(self) -> None: 86 menu = QMenu(self) 87 for i, (label, _) in enumerate(self._items): 88 act = menu.addAction(label) 89 act.setData(i) 90 if i == self._current: 91 act.setCheckable(True) 92 act.setChecked(True) 93 chosen = menu.exec(self.mapToGlobal(self.rect().bottomLeft())) 94 if chosen is not None: 95 self._apply(chosen.data())
Reemplaza QComboBox con la estética del selector de curso: botón con flecha ▾ que abre un QMenu estilizado con el tema activo.
API compatible con QComboBox:
addItem(text, userData=None) addItems(texts) currentText() / currentData() / currentIndex() setCurrentIndex(idx) / setCurrentText(text) count() / itemData(idx) Signal currentIndexChanged(int)