Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pyqt: how to remove elements from a QVBoxLayout?

I want a multi-color selection widget. The way I'm doing it is having a "+" button, and an initially empty vbox. When + is pressed, it adds a QHBoxLayout to the vbox containing a "-" button and 3 spinboxes. When the "-" button is pressed I want that row to disappear and everything to go back to looking like it did before that row was added. The code I currently have is:

    vbox = self.ui.color_layout #from QtDesigner

    hbox = QtGui.QHBoxLayout()
    remove = QtGui.QPushButton("-", parent=self)

    remove.clicked.connect(lambda: vbox.removeItem(hbox))

    rspin = QtGui.QSpinBox(parent=self)
    gspin = QtGui.QSpinBox(parent=self)
    bspin = QtGui.QSpinBox(parent=self)

    hbox.addWidget(remove)
    hbox.addWidget(QtGui.QLabel("R:", parent=self))
    hbox.addWidget(rspin)
    hbox.addWidget(QtGui.QLabel("G:", parent=self))
    hbox.addWidget(gspin)
    hbox.addWidget(QtGui.QLabel("B:", parent=self))
    hbox.addWidget(bspin)

    vbox.addLayout(hbox)

Adding widgets works fine. However, removing them results in a really messed-up looking thing where the row isn't actually removed, but the spacing is all messed up.

What am I doing wrong?

EDIT: The docs say, for removeWidget:

After this call, it is the caller's responsibility to give the widget a reasonable geometry or to put the widget back into a layout.

How do I do that? (I come from a GTK background...)

EDIT 2: I even kept track of the rows and called the takeAt function to remove it, but it still gets messed up. What gives? It looks like the layout is removed but none of the widgets are...

EDIT 3: this also doesn't work, just messes things up in a similar way:

    vbox = self.ui.color_layout

    hbox = QtGui.QHBoxLayout()

    row_widget = QtGui.QWidget(parent=self) #dummy widget to hold this stuff

    remove = QtGui.QPushButton("-", parent=self)

    def remove_func():
        vbox.removeWidget(row_widget)

    remove.clicked.connect(remove_func)

    rspin = QtGui.QSpinBox(parent=self)
    gspin = QtGui.QSpinBox(parent=self)
    bspin = QtGui.QSpinBox(parent=self)

    hbox.addWidget(remove)
    hbox.addWidget(QtGui.QLabel("R:", parent=self))
    hbox.addWidget(rspin)
    hbox.addWidget(QtGui.QLabel("G:", parent=self))
    hbox.addWidget(gspin)
    hbox.addWidget(QtGui.QLabel("B:", parent=self))
    hbox.addWidget(bspin)

    row_widget.setLayout(hbox)

    vbox.addWidget(row_widget)
like image 929
Claudiu Avatar asked May 04 '11 20:05

Claudiu


1 Answers

Try removing from parent widget, not the layout.

QLayout is not a parent, the parent for widgets being laid out is actually layout's parent. For more info and a clearer explanation see documentation on Qt layouts.

To remove widget, set its parent to None like this:

widget = QWidget()    
layout = QVBoxLayout()

btn = QPushButton("To be removed")
layout.addWidget(btn)
widget.setLayout(layout)

# later
btn.setParent(None)
like image 137
Saulius Žemaitaitis Avatar answered Sep 23 '22 18:09

Saulius Žemaitaitis