I have a column of auto-generated buttons which, if there are too many of, can squash UI elements in the window. Therefore, I want to automatically convert the single column of buttons - nominally inside of a QVBoxLayout
referred to as self.main_layout
- into a multi-column affair by:
self.main_layout
QVBoxLayout
sself.main_layout
to a QHBoxLayout
My attempt simply results in the buttons staying in a single column but now don't even resize to fill the QSplitter
frame they occupy:
app = QApplication(sys.argv)
window = TestCase()
app.exec_()
class TestCase(QMainWindow):
def __init__(self):
super().__init__()
test = QWidget()
self.layout = QVBoxLayout()
test.setLayout(self.layout)
for i in range(10):
temp_btn = QPushButton(str(i))
temp_btn.pressed.connect(self.multi_col)
self.layout.addWidget(temp_btn)
self.setCentralWidget(test)
@pyqtSlot()
def multi_col(self):
cols = [QVBoxLayout(), QVBoxLayout()]
while self.layout.count():
child = self.layout.takeAt(0)
if child.widget():
self.layout.removeItem(child)
cols[0].addItem(child)
cols[1], cols[0] = cols[0], cols[1]
self.layout = QHBoxLayout()
self.layout.addLayout(cols[0])
self.layout.addLayout(cols[1])
Any glaringly obvious thing I'm doing wrong here?
Replacing a layout of a QWidget is not so simple with assigning another object to the variable that stored the reference of the other layout. In a few lines of code you are doing:
self.layout = Foo()
widget.setLayout(self.layout)
self.layout = Bar()
An object is not the same as a variable, the object itself is the entity that performs the actions but the variable is only a place where the reference of the object is stored. For example, objects could be people and variables our names, so if they change our name it does not imply that they change us as a person.
The solution is to remove the QLayout using sip.delete and then set the new layout:
import sys
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import (
QApplication,
QHBoxLayout,
QMainWindow,
QPushButton,
QVBoxLayout,
QWidget,
)
import sip
class TestCase(QMainWindow):
def __init__(self):
super().__init__()
test = QWidget()
self.setCentralWidget(test)
layout = QVBoxLayout(test)
for i in range(10):
temp_btn = QPushButton(str(i))
temp_btn.pressed.connect(self.multi_col)
layout.addWidget(temp_btn)
@pyqtSlot()
def multi_col(self):
cols = [QVBoxLayout(), QVBoxLayout()]
old_layout = self.centralWidget().layout()
while old_layout.count():
child = old_layout.takeAt(0)
widget = child.widget()
if widget is not None:
old_layout.removeItem(child)
cols[0].addWidget(widget)
cols[1], cols[0] = cols[0], cols[1]
sip.delete(old_layout)
lay = QHBoxLayout(self.centralWidget())
lay.addLayout(cols[0])
lay.addLayout(cols[1])
def main():
app = QApplication(sys.argv)
window = TestCase()
window.show()
app.exec_()
if __name__ == "__main__":
main()