Parameter class Issue - Can't remove and add a child parameter back to the same place

46 views
Skip to first unread message

Adriel Jr.

unread,
May 26, 2016, 10:43:42 PM5/26/16
to pyqtgraph
Hello,
I'm having the following problem with PyQtGraph0.9.10+PySide1.2.2+Python2.7. I'm getting a segmentation fault after remove a Parameter, add it back, and try change its value. This error happens in the valueChange method of the WidgetParameterItem class:

self.widget.sigChanged.disconnect(self.widgetValueChanged)

It seems that it is trying to disconnect a signal of a widget that doesn't exist anymore. If we call self.widget.show() in the line before, this exception is raised:

RuntimeError: Internal C++ object (SpinBox) already deleted.

I found out that despite the widget is being recreated in the second addChild call, for some reason it is being deleted in thereafter.

This is a code example that reproduces the problem I'm having:

from pyqtgraph.parametertree import Parameter
from pyqtgraph.Qt import QtGui
from pyqtgraph.parametertree import ParameterTree


app
= QtGui.QApplication([])
t2
= ParameterTree()
t2
.show()
root
= Parameter.create(name='Root', type='group')
t2
.addParameters(root)
par
= Parameter.create(name='Par1', type='group')
par
.addChildren([{'name':'test', 'type':'int', 'limits':(500, 2000000), 'value':38400}])
root
.addChild(par)
par
.remove()
root
.addChild(par)

QtGui.QApplication.instance().exec_()

The reason I need to do it is because some of the parameters change dynamically during the execution and sometimes I need to remove and eventually add them back as a child of an existing Parameter.

Thank you in advance for any help.

Adriel

Adriel Jr.

unread,
May 27, 2016, 4:43:03 PM5/27/16
to pyqtgraph
I just found a sollution... the problem is that the signals in the Parameter class remain connected to the destroyed ParameterItem. My workaround was to capture the destroy signal of the widget objects and disconnect the ParameterItem signals:

# Disconnect the signals when the widget is gone
def __init___fix(self, param, depth):
 
ParameterItem.__init__(self, param, depth)

 
self.hideWidget = True ## hide edit widget, replace with label when not selected
 
## set this to False to keep the editor widget always visible


 
## build widget into column 1 with a display label and default button.
 w
= self.makeWidget()
 
self.widget = w
 
 
self.widget.destroyed.connect(lambda: self.param.sigValueChanged.disconnect(self.valueChanged))
 
self.widget.destroyed.connect(lambda: self.param.sigChildAdded.disconnect(self.childAdded))
 
self.widget.destroyed.connect(lambda: self.param.sigChildRemoved.disconnect(self.childRemoved))
 
self.widget.destroyed.connect(lambda: self.param.sigNameChanged.disconnect(self.nameChanged))
 
self.widget.destroyed.connect(lambda: self.param.sigLimitsChanged.disconnect(self.limitsChanged))
 
self.widget.destroyed.connect(lambda: self.param.sigDefaultChanged.disconnect(self.defaultChanged))
 
self.widget.destroyed.connect(lambda: self.param.sigOptionsChanged.disconnect(self.optsChanged))
 
self.widget.destroyed.connect(lambda: self.param.sigParentChanged.disconnect(self.parentChanged))
 
 
self.eventProxy = EventProxy(w, self.widgetEventFilter)

 
...

WidgetParameterItem.__init__ = __init___fix

Reply all
Reply to author
Forward
0 new messages