7

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)
Claudiu
  • 224,032
  • 165
  • 485
  • 680

1 Answers1

12

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)
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
Saulius Žemaitaitis
  • 2,956
  • 3
  • 29
  • 36
  • 1
    what's the parent widget? it's in a `QDialog` but it has [no remove function](http://doc.qt.nokia.com/latest/qdialog-members.html) of any kind. also weird.. i assume a qdialog was a container. i see a `children` function but apparently no way to put children in it.. – Claudiu May 05 '11 at 14:33
  • i found the parent widget, but how do i remove it? there's no `removeChild` or anything.. – Claudiu May 05 '11 at 14:53