I try to toggle a splitter container between two widgets keeping the actual size of the splitter. For this I use QSplitter.sizes() to read the actual size and QSplitter.setSizes() after I toggle my widgets.
The problem is that I have a QToolButton which I resize with setFixedSize() in a resizeEvent(), and because of this when I set the new size, it often doesn't work.
I write a little script to reproduce this : In the left part of the splitter, I have a button to toggle the right part of the splitter between two classes (which are QWidgets).
A little precision : I want to keep my QToolbutton in a 1:1 aspect ratio.
Here a demo : https://webmshare.com/play/5Bmvn
So here the script :
from PyQt4 import QtGui, QtCore
minSize = 50
maxSize = 350
class mainWindow(QtGui.QWidget):
def __init__(self):
super(mainWindow, self).__init__()
self.layout = QtGui.QVBoxLayout(self)
self.splitter = QtGui.QSplitter(QtCore.Qt.Horizontal, self)
self.splitter.setHandleWidth(20)
self.layout.addWidget(self.splitter)
wgt_left = QtGui.QWidget()
lyt_left = QtGui.QVBoxLayout(wgt_left)
self.btn_toggleSplitter = QtGui.QPushButton('Toggle Button')
self.btn_toggleSplitter.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
self.btn_toggleSplitter.setCheckable(True)
lyt_left.addWidget(self.btn_toggleSplitter)
self.splitter.addWidget(wgt_left)
self.first = panel('1')
self.second = panel('2')
self.splitter.addWidget(self.first)
self.width = self.first.size()
self.btn_toggleSplitter.clicked.connect(self.ToggleParent)
def ToggleParent(self):
self.sizes = self.splitter.sizes()
if self.btn_toggleSplitter.isChecked() == True:
self.first.setParent(None)
self.splitter.addWidget(self.second)
else :
self.second.setParent(None)
self.splitter.addWidget(self.first)
self.splitter.setSizes(self.sizes)
class panel(QtGui.QWidget):
def __init__(self, text):
super(panel, self).__init__()
lyt_main = QtGui.QVBoxLayout(self)
lyt_icon = QtGui.QHBoxLayout()
self.tbtn_icon = QtGui.QToolButton()
self.tbtn_icon.setText(text)
self.tbtn_icon.setMinimumSize(QtCore.QSize(minSize,minSize))
self.tbtn_icon.setMaximumSize(QtCore.QSize(maxSize,maxSize))
lyt_icon.addWidget(self.tbtn_icon)
lyt_horizontal = QtGui.QHBoxLayout()
lyt_horizontal.addWidget(QtGui.QPushButton('3'))
lyt_horizontal.addWidget(QtGui.QPushButton('4'))
lyt_main.addWidget(QtGui.QLabel('Below me is the QToolButton'))
lyt_main.addLayout(lyt_icon)
lyt_main.addLayout(lyt_horizontal)
lyt_main.addWidget(QtGui.QPlainTextEdit())
def resizeEvent(self, event):
w = panel.size(self).width()
h = panel.size(self).height()
size = min(h, w)-22
if size >= maxSize:
size = maxSize
elif size <= minSize:
size = minSize
self.tbtn_icon.setFixedSize(size, size)
app = QtGui.QApplication([])
window = mainWindow()
window.resize(600,300)
window.show()
app.exec_()
Thanks
You are looking for QtGui.QStackedWidget
. Adding the widgets to this on the right side of your splitter will change the code around self.first
and self.second
's construction to this:
self.stack_right = QtGui.QStackedWidget()
self.splitter.addWidget(self.stack_right)
self.first = panel('1')
self.second = panel('2')
self.stack_right.addWidet(self.first)
self.stack_right.addWidget(self.second)
Then your ToggleParent
method:
def ToggleParent(self):
if self.btn_toggleSplitter.isChecked() == True:
self.stack_right.setCurrentWidget(self.second)
else:
self.stack_right.setCurrentWidget(self.first)
This will avoid the awkwardness of caching and manually resizing your widgets.
Addendum: The tool button scaling is really a separate question, but here's a tip:
Have a look at the heightForWidth
layout setting for lyt_left
. This will help you keep a 1:1 ratio for the QToolButton
. You currently have a size policy of Preferred/Expanding, which doesn't make sense if you need a 1:1 aspect ratio. I highly recommend this over manually resizing the tool button while handling an event. Generally, calling setFixedSize
more than once on a widget should be considered a last resort. Let the layouts do the work.
Addendum to addendum: doing a little poking (it's been awhile), you may need to inherit from QToolButton
and reimplement the hasHeightForWidth()
and heightForWidth()
methods. There are a plethora of questions addressing the subject here. Just search for heightForWidth.