Python 删除PlotWidget后,如何删除tab小部件中的空白(void)?

Python 删除PlotWidget后,如何删除tab小部件中的空白(void)?,python,python-3.x,object,pyqt5,signals-slots,Python,Python 3.x,Object,Pyqt5,Signals Slots,我有一个小的仪表板应用程序,我可以在其中动态添加和删除图形。问题是,当我单击x按钮(kill graph窗口小部件)时,图形从视图中消失,但在顶部剩余的图形上方留下一个空白(请参见所附的屏幕截图) 我在这方面几乎是一个完全的初学者,但我怀疑我没有正确地处理删除小部件和对象的问题 在下面的简化代码中,我有一个类dashboard\u tab,通过单击按钮,我创建了一个add\u new\u graph对象,它创建了一个新的图形小部件self.graphWidget=pg.PlotWidget()

我有一个小的仪表板应用程序,我可以在其中动态添加和删除图形。问题是,当我单击x按钮(kill graph窗口小部件)时,图形从视图中消失,但在顶部剩余的图形上方留下一个空白(请参见所附的屏幕截图)

我在这方面几乎是一个完全的初学者,但我怀疑我没有正确地处理删除小部件和对象的问题

在下面的简化代码中,我有一个类
dashboard\u tab
,通过单击按钮,我创建了一个
add\u new\u graph
对象,它创建了一个新的图形小部件
self.graphWidget=pg.PlotWidget()

启动图形小部件close(或kill)时,我调用以下代码:

def kill_widget(self):
        self.lay.removeWidget(self.graphWidget)
        self.graphWidget.deleteLater()
        self.graphWidget = None
这似乎是可行的,因为graph小部件从视图中消失了,而不是不需要的空白

然后,我的想法是也杀死
add\u new\u graph
对象…如果它与我的问题有任何关系的话…通过从
add\u new\u graph
对象创建一个信号返回到
dashboard\u选项卡
对象…但它无法让它工作

因此,我的问题是:

  • 删除小部件后出现不需要的空白最可能的原因是什么
  • 我是否也必须删除对象才能进行正确编码
任何方向正确的点都将不胜感激

class MainWindow(QtWidgets.QWidget):
    def __init__(self, parent):
        super(QtWidgets.QWidget, self).__init__(parent)
        self.layout = QtWidgets.QVBoxLayout(self)

        self.tab_holder = QtWidgets.QTabWidget()
        tab1 = dashboard_tab()

        self.tab_holder.addTab(tab1, "Dashboard")
        self.layout.addWidget(self.tab_holder)


class dashboard_tab(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.lay = QtWidgets.QVBoxLayout(self)

        self.numGraphs = 0

        addGraphBtn = QtWidgets.QToolButton()
        addGraphBtn.setText("  Add Graph")

        addGraphBtnMenu = QtWidgets.QMenu()
        addGraphBtnMenu.addAction('Add Temp Graph', self.add_graph)
        addGraphBtn.setMenu(addGraphBtnMenu)

        self.lay.addWidget(addGraphBtn)

    def add_graph(self):
        # Create a unique graph name
        self.name = ("graph" + str(self.numGraphs))

        self.graph = add_new_graph(self.name)
        self.lay.addWidget(self.graph)

        # Up graph name index every time a new graph is created
        self.numGraphs += 1


class add_new_graph(QtWidgets.QWidget):

    def __init__(self, name):
        super().__init__()
        self.name = name

        self.lay = QtWidgets.QHBoxLayout(self)

        self.graphWidget = pg.PlotWidget()
        self.killWidgetBtn = QtWidgets.QPushButton('')
        self.killWidgetBtn.clicked.connect(self.kill_widget)

        self.lay.addWidget(self.killWidgetBtn)
        self.lay.addWidget(self.graphWidget)

    def kill_widget(self):
        self.lay.removeWidget(self.killWidgetBtn)
        self.killWidgetBtn.deleteLater()
        self.killWidgetBtn = None

        self.lay.removeWidget(self.graphWidget)
        self.graphWidget.deleteLater()
        self.graphWidget = None


if __name__ == "__main__":

    app = QtWidgets.QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())
仪表板应用程序屏幕截图


发生的事情是,您只删除了子部件(图形和按钮),而没有删除添加到布局中的容器部件

即使删除了这些对象,容器也有一个由布局给定的最小大小(取决于操作系统和当前样式,它们通常在5到10像素之间),这就是您可以看到的“空白”

您可以删除容器,而不是删除子窗口小部件


class add_new_graph(QtWidgets.QWidget):
    def __init__(self, name):
        # ...
        self.killWidgetBtn.clicked.connect(self.deleteLater)

类添加新图形(qtwidts.QWidget):
定义初始化(self,name):
# ...
self.killWidgetBtn.clicked.connect(self.deleteLater)
无论如何,您可能更希望在删除此类小部件时收到警告,因此我建议家长有责任这样做:


class dashboard_tab(QtWidgets.QWidget):
    # ...
    def add_graph(self):
        # ...
        graph = add_new_graph(self.name)
        graph.deleteRequested.connect(self.deleteGraph)

    def deleteGraph(self, graph):
        # some warning message box, maybe?
        if QtWidgets.QMessageBox.warning(self, 'Close?', 
            'Delete the graph?', 
            QtWidgets.QMessageBox.Ok|QtWidgets.QMessageBox.Cancel
            ) != QtWidgets.QMessageBox.Ok:
                return
        graph.deleteLater()

class add_new_graph(QtWidgets.QWidget):
    deleteRequested = QtCore.pyqtSignal(object)

    def __init__(self, name):
        # ...
        self.killWidgetBtn.clicked.connect(
            lambda: self.deleteRequested.emit(self))

类dashboard_选项卡(qtwidts.QWidget):
# ...
def添加图(自):
# ...
图形=添加新图形(self.name)
graph.deleteRequested.connect(self.deleteGraph)
def deleteGraph(自身,图形):
#也许是一些警告信息框?
如果qtwidts.QMessageBox.warning(self,'Close?'),
“是否删除图形?”,
qtwidts.QMessageBox.Ok | qtwidts.QMessageBox.Cancel
) != QtWidgets.QMessageBox.Ok:
返回
graph.deleteLater()
类添加新图形(qtwidts.QWidget):
deleteRequested=QtCore.pyqtSignal(对象)
定义初始化(self,name):
# ...
self.killwidgetbn.clicked.connect(
lambda:self.deleteRequested.emit(self))

如果可以的话,我有一个建议:对类使用大写名称(这样可以很容易地将它们与函数区分开来),并且不要对它们的名称使用“操作描述”:类通常不会自己“做”事情,它们的方法会做。

您可以尝试添加
self.deleteLater()
的末尾添加新图形。kill\u widget
。谢谢!这就是我最终使用下面建议的解决方案所做的,而且它是有效的!感谢您的时间。顺便说一句……我必须删除deleteLater()函数中的“self”才能使其自运行。killwidgetbn.clicked.connect(lambda:self.deleteLater())……并感谢您提供的关于提高可读性的提示!抱歉,我在第二个示例中犯了一个错误:lambda参数应该调用
self.deleteRequested.emit(self)
,否则它就没有意义:-)。我现在已经改正了。不客气,顺便说一下:-)谢谢你的更正!顺便问一下,为什么你决定在这种情况下使用lambda函数?