pyqt: 如何从 QVBoxLayout 中移除元素?

7 投票
1 回答
9557 浏览
提问于 2025-04-16 17:00

我想要一个多颜色选择的小工具。我现在的做法是有一个“+”按钮和一个最开始是空的垂直盒子(vbox)。当按下“+”按钮时,它会在这个垂直盒子里添加一个水平盒子(QHBoxLayout),里面有一个“-”按钮和三个数字输入框(spinboxes)。当按下“-”按钮时,我希望那一行消失,所有东西恢复到添加那一行之前的样子。现在我写的代码是:

    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)

添加小工具是没问题的。但是,删除它们时却出现了很糟糕的情况,行并没有真正被删除,反而间距全乱了。

我哪里做错了?

补充:文档上说,对于removeWidget

在这个调用之后,调用者需要负责给小工具一个合理的大小,或者把小工具放回一个布局中。

我该怎么做呢?(我之前用的是GTK...)

补充2:我甚至跟踪了行,并调用了takeAt函数来删除它,但还是搞得一团糟。怎么回事?看起来布局被移除了,但小工具却没有被移除...

补充3:这个方法也不行,结果也类似地搞乱了:

    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)

1 个回答

12

试着从父组件中移除,而不是从布局中移除。

QLayout 不是一个父组件,实际上,正在布局的组件的父组件是布局的父组件。想了解更多信息和更清晰的解释,可以查看 Qt 布局的文档

要移除一个组件,可以把它的父组件设置为 None,像这样:

widget = QWidget()    
layout = QVBoxLayout()

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

# later
btn.setParent(None)

撰写回答