Qt - 在Python中保留小部件的参考

问题描述:

参考以前的question,我需要一些帮助,以便在我的应用程序中保留引用。Qt - 在Python中保留小部件的参考

首先从我的代码片段。

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”应该消失并且名为“2”的新实例QPushButton应该出现在“1”的位置。此外,列表视图现在应该保存两个项目“1”和“2”,并且该窗口应该具有“等式2”的标题。如果它是一个新窗口或与以前相同,则新内容不相关。两种变体都可以。前者是目前实施的方式。每次只能看到一个窗口。

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

稍后,如果用户选择项目“1”中的QListView则当前可见QPushButton应由QPushButton“1”来替代(从集合equationEditor),或者如果他选择第二项中的QPushButton“2”应该被显示。

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

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

Btw。我刚刚看到,前面的帖子中有一个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_()) 
+0

感谢您的代码示例。我会看看它。棘手的部分将是当列表视图中的相应项目被选中时,从内存中调用窗口。 – RaJa

+0

就像现在一样,listview中的数字恰好是'equationEditor'列表中相应的'ShowAddEquation'实例的索引;所以不应该有任何问题。 – ImportanceOfBeingErnest

+0

这是正确的。我的提示是,当在列表视图中选择一个项目时,当前显示的按钮被隐藏,并且链接到该项目的按钮被显示在当前窗口中。这就是为什么我实际上将PushButton添加到'equationEditor'而不是'ShowAddEquation'。最后,用户应该看到一个窗口,在选择一个项目时右侧视图会改变(PushButton),当用户按下按钮时会重新创建一个窗口。 – RaJa

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

# -*- 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_()) 
+0

我明白你想要什么。尽管我不相信这种结构可以保持,但是当更多真实世界的信息需要存储在Button中时,如果您对此感到满意,那很好。 – ImportanceOfBeingErnest