Qt - 在Python中保持widget的引用

时间:2016-11-04 06:30:48

标签: python pyqt pyqt4

在参考之前的question时,我需要一些帮助,以便在我的应用程序中保留引用。

首先是我的代码片段。

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对象在哪里被破坏,因为我在某处错误地处理了引用。

有人能指出更好的解决方案或我如何保留参考文献? 感谢...

修改 由于似乎存在一些混淆,我将尝试更详细地解释功能。

程序启动并创建一个窗口" Equation 1"使用QListViewQPushButton" 1"。在列表视图中列出了所有可用的QPushButton(仅在开始时为1项)。在我的实际计划中,QPushButtonQWidget,其中包含一些文本字段和QPushButton

如果用户点击" 1"按钮" 1"应该消失并且QPushButton的新实例命名为" 2"应出现在" 1"的位置。此外,列表视图现在应该包含两个项目" 1"和" 2"并且窗口应该具有标题"等式2和#34;。如果是新窗口或与之前相同,则新内容不相关。两种变体都可以。前者是目前实施的方式。可见一次只能有一个窗口。

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

稍后,如果用户选择项目" 1"在QListView中,当前可见QPushButton应替换为QPushButton" 1" (来自集合equationEditor)或者如果他选择第二项QPushButton" 2"应该显示。

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

2 个答案:

答案 0 :(得分:1)

很难理解你究竟想要做什么。看看你的代码,我想知道为什么它在失败之前甚至工作了两次。

顺便说一下。我刚才看到,上一篇文章中有quite accurate description of why it's failing,由Schollii提供

无论如何,我认为你应该为等式窗口创建一个新类。然后,主类可以跟踪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_())

答案 1 :(得分:0)

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

AutoDeleteOnIdle