Replacing a widget with another one containing splitter
-
Hi,
I’m looking into an odd issue on BoxLayout.replaceWidget in PyQt5.9
It would be great if anybody would point me to a right direction.I have the following sandbox code and the goal is to split one of the exiting widget into two widgets (on one widget) without changing the other widget in the initial screen.
The idea is to replace existing widget with another widget which contains both a new widget and the existing widget with a splitter.
In split_widget(), it returns a splitter with new widget and the existing one.
And then, main class App.split_wgt() performs the replacement by calling self.layoutV.replaceWidget(self.canvas, container_wgt).
The problem is the replaced widget size is too big. I expect the replacement area is the same size as the original widget’s width&height, but containing additional widget. As a result, each new item should have 1/2 height of the original widget.
Why I can’t control the replacement area??from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * import sys class BaseClass(QFrame): def __init__(self, base=None, parent=None): super(BaseClass, self).__init__(parent) self.parent = parent self.base = base self.setMouseTracking(True) self.mouse_pos = QPoint() self.setFrameStyle(QFrame.Box) self.show() def mouseMoveEvent(self, event): self.mouse_pos = event.pos() def mousePressEvent(self, event): print('mouse pressed at ', event.pos().x(), ',', event.pos().y()) if event.pos().y() > self.height() /2: print("Bottom insert") self.base.split_signal.emit(self, 'B') else: print("Top insert") self.base.split_signal.emit(self, 'T') class App(QWidget): split_signal = pyqtSignal(object, object) def __init__(self): super().__init__() self.setGeometry(50, 50, 500, 600) self.layoutV = QVBoxLayout() self.split_signal.connect(self.split_wgt) # Upper self.upper_widget = QFrame() self.upper_widget.setFrameStyle(QFrame.StyledPanel) self.pb = QPushButton('top', self.upper_widget) self.pb.resize(self.upper_widget.width(), self.upper_widget.height()) self.pb.clicked.connect(self.place_base) # Lower self.canvas = QWidget() self.layoutV.addWidget(self.upper_widget) self.layoutV.addWidget(self.canvas) self.setLayout(self.layoutV) def place_base(self): container_wgt = BaseClass(base=self, parent=self.canvas) # Container widget container_wgt.resize(self.canvas.width(), self.canvas.height()) @pyqtSlot(object, object) def split_wgt(self, wgt, orientation): if orientation =='T': container_wgt = QWidget() self.new_wgt = BaseClass(base=self, parent=container_wgt) new_items_spltr = self.split_widget(wgt, self.new_wgt, 'V') self.new_layout = QVBoxLayout() self.new_splitter = QSplitter(Qt.Vertical) self.new_layout.addWidget(self.new_splitter) self.new_splitter.addWidget(self.new_wgt) self.new_splitter.addWidget(wgt) container_wgt.setLayout(self.new_layout) aaa = self.layoutV.replaceWidget(self.canvas, container_wgt) container_wgt.show() def destroy_layout(self, wgt): www = wgt.layout() QWidget().setLayout(wgt.layout()) # remove the wgt's layout def split_widget(self, current_wgt, new_wgt, spltr): splitter = QSplitter(Qt.Vertical) if spltr == 'V' else QSplitter(Qt.Horizontal) current_wgt.resize(current_wgt.width() /2, current_wgt.height() /2) new_wgt.resize(current_wgt.width() /2, current_wgt.height() /2) splitter.addWidget(current_wgt) splitter.addWidget(new_wgt) return splitter if __name__ == '__main__': app = QApplication(sys.argv) ex = App() ex.show() sys.exit(app.exec_())
Many thanks in advance for your help.
Regards,
Sat -
Hi,
Wouldn't QSplitter::setSizes do what you want ?
-
Thanks for an update, SGaist.
Yes, it's what I wanted! but not 100%. I still have an issue on positioning a splitter on my "main widget".
To isolate widgets, I place each splitter on different widget(let's say container widget) on the main widget, which is something like a main window or canvas. That's safe on building complex layouts as every widget is isolated.
Looks like the isolation doesn't work when I replace an existing widget with new one containing QSplitter...What I want to achieve is like this. Click on a widget splits the widget either vertically or horizontally based on the click position.
The current problem is that the main widget shows a different behavior when I place a container widget with qsplitter. Non-splitter on the container widget can position appropriately on the main widget but qsplitter container widget can't.
I guess there should be something I'm missing when I position a widget containing QSplitter, but have no idea what it is... :<Any ideas?
Thanks,
Sat -
What behaviour do you get with QSplitter ?