from functools import partial from PySide6 import QtCore, QtWidgets, QtGui class Demo(QtWidgets.QMainWindow): def __init__(self): super(Demo, self).__init__() w = QtWidgets.QWidget(self) w.setMinimumSize(350, 200) self.setCentralWidget(w) lyt = QtWidgets.QFormLayout(w) self.setWindowTitle('HoverWidget Demo') defaullt_text = ( 'Wrapped super long checkbox text text text text ... 😛' 'Wrapped super long checkbox text text text text ...' ) fancy_check1 = FancyCheck(defaullt_text) lyt.addRow(fancy_check1) richtext = 'Rich text on a Checkbox!!
With linebreaks!🤯' fancy_check2 = FancyCheck(richtext) lyt.addRow(fancy_check2) label = QtWidgets.QLabel('Default text just turned `QtCore.Qt.RichText`') label.setTextFormat(QtCore.Qt.RichText) fancy_check3 = FancyCheck() fancy_check3.hover.add_widget(label) lyt.addRow(fancy_check3) mdtext = 'Markdown text **on a Checkbox**!! \rWith linebreaks!🤯' label = QtWidgets.QLabel(mdtext) label.setTextFormat(QtCore.Qt.MarkdownText) fancy_check5 = FancyCheck() fancy_check5.hover.add_widget(label) lyt.addRow(fancy_check5) self.check_pressed = _PressedIndicator('Mouse Pressed') self.check_released = _PressedIndicator('Mouse Released') for check in fancy_check1, fancy_check2, fancy_check3, fancy_check5: check.hover.mouse_pressed.connect(self.check_pressed.trigger) check.hover.mouse_released.connect(self.check_released.trigger) hlyt = QtWidgets.QHBoxLayout() hlyt.addWidget(self.check_pressed) hlyt.addWidget(self.check_released) lyt.addRow(hlyt) class FancyCheck(QtWidgets.QWidget): def __init__(self, text='', parent=None): super().__init__(parent) self.hlayout = QtWidgets.QHBoxLayout(self) self.hlayout.setContentsMargins(0, 0, 0, 0) self.check = QtWidgets.QCheckBox(self) self.hlayout.addWidget(self.check) self.hover = HoverWidget(self) self.hover.set_hover_widget(self.check) if text: self.label = QtWidgets.QLabel(text) self.label.setWordWrap(True) self.hover.add_widget(self.label) self.hover.clicked.connect(self.check.toggle) self.hlayout.addWidget(self.hover) self.hlayout.setStretch(1, 1) class HoverWidget(QtWidgets.QWidget): clicked = QtCore.Signal() context_menu_requested = QtCore.Signal() mouse_pressed = QtCore.Signal() mouse_released = QtCore.Signal() def __init__(self, parent): super().__init__(parent) self.hlayout = QtWidgets.QHBoxLayout(self) # self.hlayout.setContentsMargins(0, 0, 0, 0) self._hover_widget = None def set_hover_widget(self, widget): self._hover_widget = widget def add_widget(self, widget): self.hlayout.addWidget(widget) def enterEvent(self, event): self._send_hover_event(event) return super().enterEvent(event) def leaveEvent(self, event): if self._send_hover_event(event): self._hover_widget.setDown(False) return super().leaveEvent(event) def _send_hover_event(self, event): if self._hover_widget is None: return False pos = self._hover_widget.pos() pos1 = QtCore.QPoint(-1, -1) if event.type() == QtCore.QEvent.Enter: hovevent = QtGui.QHoverEvent(QtGui.QHoverEvent.HoverLeave, pos, pos1) else: hovevent = QtGui.QHoverEvent(QtGui.QHoverEvent.HoverLeave, pos1, pos) QtWidgets.QApplication.sendEvent(self._hover_widget, hovevent) QtWidgets.QApplication.sendEvent(self._hover_widget, event) return True def mousePressEvent(self, event): self.mouse_pressed.emit() if self._hover_widget is not None: if self._hover_widget.isEnabled() and event.button() == QtCore.Qt.LeftButton: self._hover_widget.setDown(True) return super().mousePressEvent(event) def mouseReleaseEvent(self, event): self.mouse_released.emit() if event.button() == QtCore.Qt.RightButton: self.context_menu_requested.emit() elif self._hover_widget is not None: if self._hover_widget.isEnabled() and event.button() == QtCore.Qt.LeftButton: self.clicked.emit() self._hover_widget.setDown(False) return super().mouseReleaseEvent(event) class _PressedIndicator(QtWidgets.QCheckBox): def __init__(self, name): super().__init__(name) self.setEnabled(False) def trigger(self): self.setChecked(True) self.setEnabled(True) QtCore.QTimer(self).singleShot(500, self._off) def _off(self): self.setChecked(False) self.setEnabled(False) def show(): app = QtWidgets.QApplication([]) win = Demo() win.show() app.exec() if __name__ == '__main__': show()