Python 删除PlotWidget后,如何删除tab小部件中的空白(void)?
我有一个小的仪表板应用程序,我可以在其中动态添加和删除图形。问题是,当我单击x按钮(kill graph窗口小部件)时,图形从视图中消失,但在顶部剩余的图形上方留下一个空白(请参见所附的屏幕截图) 我在这方面几乎是一个完全的初学者,但我怀疑我没有正确地处理删除小部件和对象的问题 在下面的简化代码中,我有一个类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()
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函数?