2016-11-04 63 views
3

參考以前的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中選擇了一個,相應的窗口小部件就應該顯示在窗口中,以便他可以再次編輯窗口小部件中的數據。

回答

1

很難理解你想要做什麼。看看你的代碼我不知道爲什麼它甚至在失敗之前工作兩次。

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

0

所以,瞭解在第一個答案給出的方法,我已經解決了我的問題後。這裏是工作代碼

# -*- 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