I'm having trouble changing the parent of the widgets added directly to a frame on PyQt5
I have a grid of frames positioned in another frame without layout, this is because I need a free positioning mechanism instead of the girdLayout.
This is my process:
- on a For Loop I Create multiple ClusterFrames and setParent(gridFrameContainer)
- Create the widgets, buttons and labels for each ClusterFrame
Everything works ok, all the ClusterFrames are displayed, resized and repositioned when I use ClusterFrame[i].setGeometry
The problem is when I need to remove a ClusterFrame[i] from the frame, as you might know, it's very hard to delete a widget if I don't have a layout.
I've tried ClusterFrame[i].close(), ClusterFrame[i].deletelater del(ClusterFrame[i])...
Since nothing has worked for me, what I do is:
- Create a topFrame
- Create a stacked Layout for topFrame
- Create gridFrameContainer
- Add gridFrameContainer to stacked Layout
- on a For Loop I Create multiple ClusterFrames and setParent(gridFrameContainer)
- Create the widgets, buttons and labels for each ClusterFrame
Here works ok, no problems here.
When I want to change the quantity of ClusterFrames
- On a For Loop I change the parent of each ClusterFrames as ClusterFrames[i].setParent(None or MainWindow)
- On the StackedLayout I delete the current gridFrameContainer
- On the StackedLayout I add a NewGridFrameContainer
- On a For Loop I change the parent of each ClusterFrames as ClusterFrames[i].setParent(NewGridFrameContainer)
But they're not displayed anymore.
It seems like I can only set the Parent once, is that right? if so, the I need to delete each ClusterFrame and create it again?
When I create the widgets of ClusterFrames, I set the parent only of the frame, but never of each widget of the cluster like buttons, labels, I suppose that they belongs to the ClusterFrame parent right?
If I change the parent of the frame ClusterFrame, should I change the parent of his widgets?
Thanks
Here's an example: (Press the button to change the parent)
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow
from PyQt5 import QtWidgets
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setWindowTitle("My Awesome App")
self.showMaximized()
self.stackedFrames = QtWidgets.QFrame()
self.stacked_frames_layout = QtWidgets.QStackedLayout()
self.clustersFrame = QtWidgets.QFrame() # Disposable each time I need to delete clusters
other_frame = QtWidgets.QFrame() # I have multiple frames for other purposes
and_other_frame = QtWidgets.QFrame() # I have multiple frames for other purposes
self.stacked_frames_layout.addWidget(self.clustersFrame)
self.stacked_frames_layout.addWidget(other_frame)
self.stacked_frames_layout.addWidget(and_other_frame)
self.stackedFrames.setLayout(self.stacked_frames_layout)
# Create 10 clusters
self.clusters = []
for i in range(10):
cluster = QtWidgets.QFrame()
cluster.setParent(self.clustersFrame)
layout = QtWidgets.QVBoxLayout()
label = QLabel("Cluster {}".format(i))
layout.addWidget(label)
cluster.setLayout(layout)
self.clusters.append(cluster)
# Set Geometry
size = 100
for i, cluster in enumerate(self.clusters):
cluster.setGeometry(i * size + 10, 0, size, size)
# Main frame
button_to_test = QtWidgets.QPushButton()
button_to_test.setText('Change grid')
button_to_test.clicked.connect(self.change_quantity)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.stackedFrames)
layout.addWidget(button_to_test)
mainFrame = QtWidgets.QFrame()
mainFrame.setLayout(layout)
self.setCentralWidget(mainFrame)
def change_quantity(self):
self.stacked_frames_layout.removeWidget(self.clustersFrame)
self.clustersFrame = QtWidgets.QFrame()
self.stacked_frames_layout.insertWidget(0, self.clustersFrame)
self.stacked_frames_layout.setCurrentIndex(0)
size = 110
self.clusters = self.clusters[:8]
for i, cluster in enumerate(self.clusters):
cluster.setParent(self.clustersFrame)
cluster.setGeometry(i * size + 10, 0, size, size)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()