Qt-在Python中保留小部件的引用

Qt-在Python中保留小部件的引用,python,pyqt,pyqt4,Python,Pyqt,Pyqt4,在引用以前的一篇文章时,我需要一些帮助,以便在我的应用程序中保留引用 首先是我的代码片段 from PyQt4 import QtGui import os, os.path import sys class mainWindowHandler(): equationEditor = [] _listview = None _window = None def __init__(self): return def sh

在引用以前的一篇文章时,我需要一些帮助,以便在我的应用程序中保留引用

首先是我的代码片段

from PyQt4 import QtGui
import os, os.path
import sys

class mainWindowHandler():

    equationEditor = []
    _listview = None
    _window = None       

    def __init__(self):
        return

    def showAddEquation(self):
        """Creates a new instance of the dynamic editor for adding an equation"""

        #create a horizontal split layout
        window = QtGui.QWidget()
        layout = QtGui.QHBoxLayout()

        current = len(self.equationEditor) - 1
        de = QtGui.QPushButton(str(current))
        self.equationEditor.append(de)

        de.clicked.connect(self.clicked)                    

        #fill list view with items from equation collection
        listview = QtGui.QListWidget()
        for equation in self.equationEditor:
            item = QtGui.QListWidgetItem()
            item.setText(equation.text())
            listview.addItem(item)            
        layout.addWidget(listview)
        layout.addWidget(de)

        window.setWindowTitle("Equation {}".format(str(current))
        window.setLayout(layout)

        self._window = window
        self._listview = listview
        window.show()

        return window

    def clicked(self):
        """Method for handling the button events in the solver settings\n
        signal = the button hit\n"""        
        return self.showAddEquation()   

if __name__ == "__main__":
    path = os.path.dirname(os.path.abspath(__file__))
    app = QtGui.QApplication(sys.argv)
    ewh = mainWindowHandler()
    window = ewh.showAddEquation()
    sys.exit(app.exec_())
应用程序(稍后)将创建一个窗口,允许操纵某些设置-在我的代码示例中,由
QPushButton
表示。这些设置稍后会写入一个txt文件,但在此之前,我会将它们保存在该窗口小部件中。我只需将小部件添加到集合中,然后从那里调用它们。这在Python级别上运行良好

现在,我有一个按钮,可以从窗口内部创建一个新的窗口实例。这也行。但直到第三次审判。在这一点上,我失去了对Qt级别上我的
QPushButton
的引用。我明白了

wrapped C/C++ object of type `QPushButton` has been deleted
尝试从我的集合中检索按钮时出错(
equationEditor
)。在Python中,它们仍然存在,但很明显,由于我在某个地方错误地处理了引用,相应的Qt对象被破坏了

有人能指出一个更好的解决方案,或者我如何保存这些参考资料吗? 谢谢


编辑: 由于似乎存在一些混淆,我将尝试更详细地解释该功能

程序启动并创建一个带有
QListView
QPushButton
的窗口“等式1”。在列表视图中,列出了所有可用的
QPushButton
(开始时仅列出1项)。在我的实际程序中,
QPushButton
是带有一些文本字段和
QPushButton
QWidget

如果用户单击“1”,则按钮“1”应消失,并且名为“2”的
QPushButton
的新实例应出现在“1”的位置。此外,listview现在应该包含两个项目“1”和“2”,窗口的标题应该是“等式2”。如果是新窗口或与以前相同的新内容,则不相关。两种变体都可以。前者是目前的实施方式。一次只能通过一个窗口显示

应将
QPushButton
的所有实例收集到一个小列表(称为
equationEditor
)中,以将它们保存在内存中。在我的实际程序中,这用于保存小部件中的所有更改,而无需将更改写入临时文件

稍后,如果用户在
QListView
中选择项目“1”,则当前可见的
QPushButton
应替换为
QPushButton
“1”(来自集合
等式编辑器
),或者如果用户选择第二个项目,则应显示
QPushButton
“2”

为什么??
稍后将使用的小部件包含大量可编辑数据。由于用户可以在任何时候编辑,因此将小部件保存在内存中而不显示它们比重新填充所有数据更容易。一旦用户在
QListView
中选择了一个,相应的小部件就会显示在窗口中,这样他就可以再次编辑小部件中的数据。

很难理解您到底想做什么。看着你的代码,我想知道为什么它在失败之前还能运行两次

顺便说一句,我刚刚看到,在上一篇文章中有一个由斯科利给出的答案

无论如何,我认为你应该为等式窗口创建一个新类。然后,主类可以跟踪
equationEditor
列表中所有打开的窗口。一旦创建,它还可以将其他打开的窗口的值添加到新窗口中

下面是它的样子

from PyQt4 import QtGui
import os, os.path
import sys

class ShowAddEquation(QtGui.QWidget):
    """Creates a new instance of the dynamic editor for adding an equation"""
    def __init__(self,parent=None):
        super(ShowAddEquation, self).__init__(parent=parent)
        #create a horizontal split layout
        layout = QtGui.QHBoxLayout()

        self.current = 0 
        self.de = QtGui.QPushButton(str(self.current))
        self.listview = QtGui.QListWidget()

        layout.addWidget(self.listview)
        layout.addWidget(self.de)

        self.setWindowTitle("Equation Editor")
        self.setLayout(layout)

        self.show()

    def setCurrent(self, current):
        self.current=current
        self.de.setText(str(self.current))



class mainWindowHandler():

    equationEditor = []

    def __init__(self):
        return

    def clicked(self): 
        se = ShowAddEquation()
        self.equationEditor.append(se)
        se.de.clicked.connect(self.clicked)
        current = len(self.equationEditor) - 1
        se.setCurrent(current)
        for equation in self.equationEditor:
            item = QtGui.QListWidgetItem()
            item.setText(str(equation.current))
            se.listview.addItem(item)  


if __name__ == "__main__":
    path = os.path.dirname(os.path.abspath(__file__))
    app = QtGui.QApplication(sys.argv)
    ewh = mainWindowHandler()
    ewh.clicked()
    sys.exit(app.exec_())

因此,在理解了第一个答案中给出的方法之后,我已经解决了我的问题。这是工作代码

# -*- coding: utf-8 -*-
"""
Created on Sat Sep  3 14:31:15 2016

"""

from PyQt4 import QtGui
from PyQt4 import QtCore

import os, os.path
import sys

class mainWindowHandler():

    equationEditor = []
    _listview = None
    _window = None       

    def __init__(self):
        return

    def showAddEquation(self):
        """Creates a new instance of the dynamic editor for adding an equation"""

        #create a horizontal split layout
        self._window = QtGui.QWidget()
        layout = QtGui.QHBoxLayout()
        self._listview = QtGui.QListWidget()
        layout.addWidget(self._listview)

        self._listview.clicked[QtCore.QModelIndex].connect(self.changed)        

        self._window.setLayout(layout)       
        #populate the right side of the layout with a button
        self.clicked()        

        self._window.show()

        return self._window

    def clicked(self):
        """Make a new button instance and add it to the window and the collection"""        
        window = self._window
        layout = window.layout()

        current = len(self.equationEditor) - 1
        de = QtGui.QPushButton(str(current))
        self.equationEditor.append(de)

        de.clicked.connect(self.clicked)    
        #close the currently shown button
        item = layout.takeAt(1)
        if item is not None:
            item.widget().close()                
        layout.addWidget(de)

        #fill list view with items from material collection
        item = QtGui.QListWidgetItem()
        item.setText(de.text())
        self._listview.addItem(item)     
        self._window.setWindowTitle("Equation Editor {}".format(str(current)))        

    def changed(self, index):
        """hide the object on the right side of the layout and show the button at position index in the collection"""
        layout = self._window.layout()
        item = layout.takeAt(1)
        item.widget().close()
        # insert the selected button from the collection
        de = self.equationEditor[index.row()]
        layout.insertWidget(1, de)        
        self._window.setWindowTitle("Equation Editor {}".format(str(index.row() - 1)))        
        de.show()        


if __name__ == "__main__":
    path = os.path.dirname(os.path.abspath(__file__))
    app = QtGui.QApplication(sys.argv)
    ewh = mainWindowHandler()
    window = ewh.showAddEquation()
    sys.exit(app.exec_())

谢谢你的代码示例。我来看看。棘手的部分是在选择了listview中的相应项后从内存中调用窗口。现在,listview中的数字正是
equationEditor
列表中相应的
ShowAddEquation
实例的索引;所以应该没什么问题,没错。我的注意事项是,当在listview中选择一个项目时,当前显示的按钮被隐藏,链接到该项目的按钮显示在当前窗口中。这就是为什么我实际上将按钮添加到
equalationeditor
而不是
ShowAddEquation
。最后,用户应该会看到一个窗口,当用户选择一个项目时,右视线会发生变化(按钮),当用户按下按钮时,右视线会重新创建。我不明白你的意思。应该有一个窗口还是多个窗口?开始时,您有一个窗口、一个列表项和一个按钮。接下来会发生什么?如果你想更详细地解释这个问题,也许你可以更新你的问题。请记住,您不能在多个窗口中使用相同的按钮。我已尝试更详细地解释我的问题。希望现在一切都清楚了。我知道你现在想要什么了。虽然我不相信这种结构可以保存,但当按钮中需要存储更多真实世界的信息时,如果您对它感到满意,就可以了。