4

I keep getting this RuntimeError which I'm not sure how to fix. Here's what I'm trying to accomplish. I want to update this QTableWidget with values dynamically as I'm clicking on different items in my QTreeView. On the most part, my code works except when I click on my second item and I need to update my QTableWidgt which is when I run into this "RuntimeError: underlying C/C object has been deleted". Here's a snippet of my code:

def BuildTable( self ):
    ...
    for label in listOfLabels :
        attr = self.refAttr[label]
        self.table.setItem(row, 0, QtGui.QTableWidgetItem( label ) )

        tableItem = QtGui.QTableWidgetItem( str(attr.GetValue()) )
        self.table.setItem(row, 1, tableItem )
        someFunc = functools.partial( self.UpdateValues, tableItem, label )                     

        QtCore.QObject.connect(self.table, QtCore.SIGNAL('itemChanged(QTableWidgetItem*)'), someFunc)   

def UpdateValues(self, tableItem, label):
    print '--------------------------------'
    print 'UPDATING TEXT PROPERTY VALUE!!!'
    print tableItem.text()
    print label

The compiler complains errors on the line, "print tableItem.text()"

Thx!

jdi
  • 90,542
  • 19
  • 167
  • 203
JLYK
  • 391
  • 9
  • 22
  • 1
    Have you inherited from any QT types? You often get this message if you inherit but forget to call the c++ ctor. – Alex Wilson Jun 26 '12 at 18:48
  • There shouldn't be any inherited QT Types. I declared my table as so: self.table = QtGui.QTableWidget() – JLYK Jun 26 '12 at 18:52
  • Nope. Just complains about the "print tableItem.text()" line saying "RuntimeError: underlying C/C++ object has been deleted". Mind you, this only happens if I click on a second item which forces the QTableWidget to update. – JLYK Jun 26 '12 at 19:33
  • @JLYK: Yes, its because you are holding on to TableWidgetItem references that can be deleted. See my answer – jdi Jun 26 '12 at 19:34
  • Can you do me a favor? All 6 of your current questions are open. Can you please accept some answers if you feel they have been properly addressed? Its going to start turning away others from helping you. I realized I answered a question for you back in May that is still open. If these previous questions are not answered to your liking, try and give the people some comments about them. – jdi Jun 26 '12 at 22:19

1 Answers1

1

I believe the issue is that you are binding up a callback with a QTableWidget item and making many many connections (bad). Items can change. Thus, they can be deleted making your callback dead.

What you want is to just let the itemChanged signal tell you what item changed, the moment it happens.

self.table = QtGui.QTableWidget()
...
# only do this once...ever...on the init of the table object
QtCore.QObject.connect(
    self.table, 
    QtCore.SIGNAL('itemChanged(QTableWidgetItem*)'), 
    self.UpdateValues
)

And then in your SLOT, it will receive the item:

def UpdateValues(self, tableItem):
    print '--------------------------------'
    print 'UPDATING TEXT PROPERTY VALUE!!!'
    print tableItem.text()
jdi
  • 90,542
  • 19
  • 167
  • 203
  • Hmm...if it's not in a for loop, then how do I know which tableItem I'm passing in? My UpdateValues function also takes multiple parameters. – JLYK Jun 26 '12 at 19:44
  • You dont bind the slot to the item. The table notifies you when any item changes and what that item is. It will pass it. – jdi Jun 26 '12 at 20:13
  • Just wanted to add, you can do what your were doing with partial and binding arguments. Just use keyword parameters in your SLOT after the expected qt argument. Like: partial(func, color='red'). But be carefull with any objects that can come and go. – jdi Jun 26 '12 at 20:38
  • what happens if one of my tableitems is a combobox? Can I keep it in my for loop? It seems to only call it only when I change the value. – JLYK Jun 26 '12 at 21:22
  • Regardless of any kind of widget, if you make the same connection more than once, it will get called multiple times. Can you explain why you think you require making connections in a for loop? – jdi Jun 26 '12 at 22:11
  • If I'm creating the combo box within my for loop, how would I create a connection to it otherwise? Because when I change the index of my combo, it does not trigger a call to the UpdateValues function. – JLYK Jun 26 '12 at 22:39
  • Are you talking about using `table.setCellWidget()` to add combo boxes into your table? If that is the case, then you are setting a connection from the signal of the combobox -> a SLOT. No matter what, you do not create multiple connections FROM the table signal TO multiple items. – jdi Jun 26 '12 at 22:43
  • @JLYK: If you accept your other answers, you will have enough points for us to have a chat about this issue. – jdi Jun 26 '12 at 22:51
  • Yes I am using table.setCellWidget() for my combo box. I guess it's okay then because I'm creating unique connections per combobox. – JLYK Jun 26 '12 at 23:09
  • Yes, only if you are connecting FROM the signals of the combobox. – jdi Jun 26 '12 at 23:10