如何一个一个删除小部件

How to delete widgets one by one

每次单击“打开”按钮时,我都会添加一个额外的图表。

我希望能够使用“关闭”按钮一张一张地删除图表,除了第一个。

我只能删除一张图表。 也许这是我用的“splitter”,错了。 我一直尝试打印“print(self.lay.count())”,但结果是两个。

from PyQt5 import QtCore, QtGui, QtWidgets, QtChart

mas =[1.33, 1.15, 1.55, 1.65, 1.64, 1.91, 1.33, 2.3, 1.5, 1.35, 2.52, 1.77, 1.7, 1.87, 2.0, 1.55, 1.73, 2.1,
              1.33, 1.15, 1.55, 1.92, 1.64, 1.91, 1.33, 1.71, 1.5, 1.35, 1.22, 1.77, 1.7, 1.87, 2.7, 1.55, 1.73, 2.1,
              1.33, 1.15, 1.55, 1.92, 1.64, 1.91, 1.33, 1.71, 1.5, 1.35, 1.22, 1.77, 1.7, 1.87, 2.0, 1.55, 1.73, 2.1]
x = len(mas)

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        self._chart_view = QtChart.QChartView()
        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)

        self.open = QtWidgets.QPushButton()
        self.open.setText("Open")
        self.open.clicked.connect(self.open_clicked)
        self.close = QtWidgets.QPushButton()
        self.close.setText("Close")
        self.close.clicked.connect(self.close_clicked)

        self.hbox = QtWidgets.QHBoxLayout()
        self.hbox.addWidget(self.open)
        self.hbox.addWidget(self.close)

        self.lay = QtWidgets.QVBoxLayout(central_widget)
        self.lay.addWidget(self._chart_view)
        self.lay.insertLayout(0, self.hbox)

        self._chart = QtChart.QChart()
        self._line_serie = QtChart.QLineSeries()

        for i in range(0, len(mas)):
            self._line_serie.append(QtCore.QPointF(i, mas[i]))

        self._chart.addSeries(self._line_serie)
        self._chart.createDefaultAxes()
        self._chart.legend().hide()
        self._chart_view.setChart(self._chart)

    def open_clicked(self):
        number = self.lay.count() - 1
        self.item = self.lay.itemAt(number)
        self._chart_view = QtChart.QChartView()

        self.splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)
        for w in (self.item.widget(), self._chart_view):
            self.splitter.addWidget(w)
        self.lay.addWidget(self.splitter)

        self._chart = QtChart.QChart()
        self._line_serie = QtChart.QLineSeries()
        for i in range(0, len(mas)):
            self._line_serie.append(QtCore.QPointF(i, mas[i]))
        self._chart.addSeries(self._line_serie)
        self._chart.createDefaultAxes()
        self._chart_view.setChart(self._chart)

        print(self.lay.count())


    def close_clicked(self):
        self._chart_view.deleteLater()


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

问题是“self._chart_view”存储了最后一个 QChartView,因此当使用 deleteLater 删除它时,它将指向一个未保留的内存,导致错误想要删除它,因为它已经被删除。另一方面,我不认为需要使用 QVBoxLayout,但 QSplitter 就足够了,最后一个小部件可以使用 QSplitter::widget() 方法访问。

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)

        self.open_btn = QtWidgets.QPushButton("Open")
        self.open_btn.clicked.connect(self.add_chartview)
        self.close_btn = QtWidgets.QPushButton("Close")
        self.close_btn.clicked.connect(self.remove_chartview)

        hbox = QtWidgets.QHBoxLayout()
        hbox.addWidget(self.open_btn)
        hbox.addWidget(self.close_btn)

        self.splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)

        lay = QtWidgets.QVBoxLayout(central_widget)
        lay.addLayout(hbox)
        lay.addWidget(self.splitter, stretch=1)

        self.add_chartview()

    def add_chartview(self):
        chart_view = QtChart.QChartView()
        chart = QtChart.QChart()
        line_serie = QtChart.QLineSeries()
        for i, value in enumerate(mas):
            line_serie.append(QtCore.QPointF(i, value))
        chart.addSeries(line_serie)
        chart.createDefaultAxes()
        chart_view.setChart(chart)
        self.splitter.addWidget(chart_view)

    def remove_chartview(self):
        count = self.splitter.count()
        if count > 1:
            w = self.splitter.widget(count - 1)
            if w is not None:
                w.deleteLater()