Python 内部C++;对象已删除(pyside)

Python 内部C++;对象已删除(pyside),python,qt,pyside,Python,Qt,Pyside,此程序的目的是将tradeWindow显示为QWidget,然后在每次调用doStuff(通过按钮)时显示QDialog(如果有结果)。代码第一次运行,但第二次收到错误消息时: 回溯(最近一次呼叫最后一次): 文件“GUI.py”,第68行,在doStuff中 弹出=对话框((Qt.WindowSystemMenuHint | Qt.WindowTitleHint),popLayout) 文件“GUI.py”,第47行,在_init中__ self.setLayout(popLayout) Ru

此程序的目的是将tradeWindow显示为QWidget,然后在每次调用doStuff(通过按钮)时显示QDialog(如果有结果)。代码第一次运行,但第二次收到错误消息时:

回溯(最近一次呼叫最后一次):
文件“GUI.py”,第68行,在doStuff中
弹出=对话框((Qt.WindowSystemMenuHint | Qt.WindowTitleHint),popLayout)
文件“GUI.py”,第47行,在_init中__
self.setLayout(popLayout)
RunTimeRebug:内部C++对象(PySale.QtGuG.QHBox版式)已经删除。
当我第一次关闭QDialog时,我的布局似乎被删除了。 将
popLayout=QHBoxLayout()
移动到
doStuff
的开头,我认为这会解决问题,但会出现以下错误:

回溯(最近一次呼叫最后一次):
文件“GUI.py”,第69行,在doStuff中
弹出=对话框((Qt.WindowSystemMenuHint | Qt.WindowTitleHint),popLayout)
文件“GUI.py”,第47行,在_init中__
self.setLayout(popLayout)
NameError:未定义名称“popLayout”
这对我来说没有多大意义,因为它应该在被引用之前得到定义?反正我也找不到问题。我相信我的很多代码都可以改进,因为我对类等非常陌生

如果你有任何关于如何每次打开QDialog的技巧,这些技巧比我目前尝试的或其他有用的技巧要好,请毫不犹豫地提及。(尝试忽略糟糕的命名约定,我将在将来修复它。)

谢谢你的帮助


关闭
对话框
后,引用它的
弹出窗口
变量超出范围,Python将对其进行垃圾收集。这会导致整个基础C++对象,包括所有子部件和布局,都被删除。但是,您保留了对对话框使用的布局的引用,因此在您第二次尝试打开对话框时,该布局将被删除

我觉得奇怪的是,您在
对话框
类之外执行
对话框
类的所有初始化。相反,我建议在
对话框
类中移动
popLayout
的创建,以及
的所有创建和设置。这样,每次打开对话框时都会创建布局

您需要将
gameResults
作为参数添加到
对话框
\uuuu init\uuuuu
方法中,并且您还可以删除当前存在的
布局
参数,因为它未被使用

完成此操作后,您的
对话框
类应如下所示:

class Dialog(QDialog):
    def __init__(self, flags, gameResults):
        super().__init__()
        self.setWindowFlags(flags)    
        self.resize(800,500)
        popLayout = QHBoxLayout()
        self.setLayout(popLayout)

        table = Table(popLayout)
        table.setRowCount(len(gameResults))
        table.setColumnCount(2);
        table.setHorizontalHeaderItem(0, QTableWidgetItem("Game"))
        table.setHorizontalHeaderItem(1, QTableWidgetItem("URL"))
        for index, game in enumerate(sorted(gameResults)):
            table.setItem(index,0,QTableWidgetItem(game))
            table.item(index,0).setFlags( Qt.ItemIsSelectable |  Qt.ItemIsEnabled )
            table.setItem(index,1,QTableWidgetItem('http://store.steampowered.com/app/'+gameResults[game]+'/'))
            table.item(index,1).setFlags( Qt.ItemIsSelectable |  Qt.ItemIsEnabled )
        table.resizeColumnsToContents()
def doStuff():
    gameResults = {'doom' : '111232', 'quake' : '355324'}
    if len(gameResults) > 0:
        popup = Dialog((Qt.WindowSystemMenuHint | Qt.WindowTitleHint), gameResults)
        popup.exec_()
    else:
        msgBox = QMessageBox()
        msgBox.setText("No results.")
        msgBox.exec_()
您的
doStuff()
方法应该如下所示:

class Dialog(QDialog):
    def __init__(self, flags, gameResults):
        super().__init__()
        self.setWindowFlags(flags)    
        self.resize(800,500)
        popLayout = QHBoxLayout()
        self.setLayout(popLayout)

        table = Table(popLayout)
        table.setRowCount(len(gameResults))
        table.setColumnCount(2);
        table.setHorizontalHeaderItem(0, QTableWidgetItem("Game"))
        table.setHorizontalHeaderItem(1, QTableWidgetItem("URL"))
        for index, game in enumerate(sorted(gameResults)):
            table.setItem(index,0,QTableWidgetItem(game))
            table.item(index,0).setFlags( Qt.ItemIsSelectable |  Qt.ItemIsEnabled )
            table.setItem(index,1,QTableWidgetItem('http://store.steampowered.com/app/'+gameResults[game]+'/'))
            table.item(index,1).setFlags( Qt.ItemIsSelectable |  Qt.ItemIsEnabled )
        table.resizeColumnsToContents()
def doStuff():
    gameResults = {'doom' : '111232', 'quake' : '355324'}
    if len(gameResults) > 0:
        popup = Dialog((Qt.WindowSystemMenuHint | Qt.WindowTitleHint), gameResults)
        popup.exec_()
    else:
        msgBox = QMessageBox()
        msgBox.setText("No results.")
        msgBox.exec_()
我对您的代码进行了这些更改,并且能够多次打开该对话框

我将让您以同样的方式在
窗口中移动主窗口设置代码


最后,请注意,我只使用PyQt测试过这个。不过,我希望我的更改也能对PySide起作用。

谢谢:)我正在将代码重构为一种更面向类的方法,因为我以前有一个“原型”并在运行,昨天我刚刚学习了类的基础知识。总是觉得使用起来有点烦人,但从现在起,我想我会更喜欢上课。还是新的,尽管如此,感谢所有的投入。我现在将浏览这篇文章,并在接受答案之前进行修改,但感谢你提供了一篇内容丰富的帖子:)效果很好,似乎也是一种更好的处理问题的方式。我现在也将对主窗口进行更改。也谢谢你教育我:)我真的不确定在上课的时候我应该把界限划在哪里。现在我在考虑是否应该在主窗口中定义doStuff函数,而我应该只传递游戏结果?@raecer:我建议将
doStuff()
函数移到主窗口中。