Scoodood | 2020-09-25 05:16:36 UTC | #1
The default QSplitter Widget only has splitterMoved
signal. I would like to add a doubleClicked
signal so that I can make the QSplitter widget can move all the way to the left on a double clicking event, and then double clicking it again will restore to its previous position. Below are my starter code. Any idea how to go from here?
from PySide2 import QtWidgets, QtCore
class Example(QtWidgets.QWidget):
def __init__(self):
super().__init__()
splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
textedit1 = QtWidgets.QTextEdit()
textedit2 = QtWidgets.QTextEdit()
splitter.addWidget(textedit1)
splitter.addWidget(textedit2)
splitter.setSizes([200,200])
layout = QtWidgets.QVBoxLayout()
layout.addWidget(splitter)
self.setLayout(layout)
splitter.splitterMoved.connect(self.handler)
# trying to do something like this...
#splitter.doubleClicked.connect(self.handler)
def handler(self, pos):
print('pos', pos)
if __name__ == '__main__':
app = QtWidgets.QApplication([])
w = Example()
w.show()
app.exec_()
martin | 2020-09-30 20:45:37 UTC | #2
Hey @Scoodood I knocked together a simple custom widget for this -- it implements a double click event handler which stores and restores a slide position.
class ToggleSplitter(QtWidgets.QSplitter):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Store the previos size of the left hand panel.
self._previous_state = None
def mouseDoubleClickEvent(self, e):
sizes = self.sizes()
if sizes[0] == 0 and self._previous_state:
sizes = self._previous_state
else:
# Store the size so we can return to it.
self._previous_state = sizes[:] # store copy so change below doesn't affect stored.
sizes[0] = 0
self.setSizes(sizes)
If you run it you'll notice the slight problem -- you can't actually double click on the splitter itself, just on the (tiny space) in the frame next to it. Move your mouse around the edge of the splitter until it turns into an arrow, then double click.
The problem is that QSplitter
is a compound widget with the handles themselves QSplitterHandle objects. However, QSplitter
has a createHandle
method we can override allowing us to return our own custom handles -- and we can put our double-click handler on there instead.
Full working example ...
Create GUI Applications with Python & Qt5 by Martin Fitzpatrick — (PyQt5 Edition) The hands-on guide to making apps with Python — Over 10,000 copies sold!
from PySide2 import QtWidgets, QtCore
class ToggleSplitterHandle(QtWidgets.QSplitterHandle):
def mouseDoubleClickEvent(self, e):
self.parent().toggle_collapse()
class ToggleSplitter(QtWidgets.QSplitter):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Store the previos size of the left hand panel.
self._previous_state = None
def createHandle(self):
return ToggleSplitterHandle(self.orientation(), self)
def toggle_collapse(self):
sizes = self.sizes()
if sizes[0] == 0 and self._previous_state:
sizes = self._previous_state
else:
# Store the size so we can return to it.
self._previous_state = sizes[:] # store copy so change below doesn't affect stored.
sizes[0] = 0
self.setSizes(sizes)
class Example(QtWidgets.QWidget):
def __init__(self):
super().__init__()
splitter = ToggleSplitter(QtCore.Qt.Horizontal)
textedit1 = QtWidgets.QTextEdit()
textedit2 = QtWidgets.QTextEdit()
splitter.addWidget(textedit1)
splitter.addWidget(textedit2)
splitter.setSizes([200,200])
layout = QtWidgets.QVBoxLayout()
layout.addWidget(splitter)
self.setLayout(layout)
splitter.splitterMoved.connect(self.handler)
def handler(self, pos):
print('pos', pos)
if __name__ == '__main__':
app = QtWidgets.QApplication([])
w = Example()
w.show()
app.exec_()
Scoodood | 2020-09-30 20:59:09 UTC | #3
Thanks @martin. This is awesome!!
Create GUI Applications with Python & Qt6 by Martin Fitzpatrick — (PyQt6 Edition) The hands-on guide to making apps with Python — Over 10,000 copies sold!