Cleaned up parametertree example
This commit is contained in:
parent
2213dea9d8
commit
4384944952
@ -11,7 +11,7 @@ examples = OrderedDict([
|
|||||||
('Command-line usage', 'CLIexample.py'),
|
('Command-line usage', 'CLIexample.py'),
|
||||||
('Basic Plotting', 'Plotting.py'),
|
('Basic Plotting', 'Plotting.py'),
|
||||||
('ImageView', 'ImageView.py'),
|
('ImageView', 'ImageView.py'),
|
||||||
('ParameterTree', '../parametertree'),
|
('ParameterTree', 'parametertree.py'),
|
||||||
('Crosshair / Mouse interaction', 'crosshair.py'),
|
('Crosshair / Mouse interaction', 'crosshair.py'),
|
||||||
('Video speed test', 'VideoSpeedTest.py'),
|
('Video speed test', 'VideoSpeedTest.py'),
|
||||||
('Plot speed test', 'PlotSpeedTest.py'),
|
('Plot speed test', 'PlotSpeedTest.py'),
|
||||||
|
160
examples/parametertree.py
Normal file
160
examples/parametertree.py
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
This example demonstrates the use of pyqtgraph's parametertree system. This provides
|
||||||
|
a simple way to generate user interfaces that control sets of parameters. The example
|
||||||
|
demonstrates a variety of different parameter types (int, float, list, etc.)
|
||||||
|
as well as some customized parameter types
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import initExample ## Add path to library (just for examples; you do not need this)
|
||||||
|
|
||||||
|
import pyqtgraph as pg
|
||||||
|
from pyqtgraph.Qt import QtCore, QtGui
|
||||||
|
|
||||||
|
|
||||||
|
import collections
|
||||||
|
app = QtGui.QApplication([])
|
||||||
|
import pyqtgraph.parametertree.parameterTypes as pTypes
|
||||||
|
from pyqtgraph.parametertree import Parameter, ParameterTree, ParameterItem, registerParameterType
|
||||||
|
|
||||||
|
|
||||||
|
## test subclassing parameters
|
||||||
|
## This parameter automatically generates two child parameters which are always reciprocals of each other
|
||||||
|
class ComplexParameter(pTypes.GroupParameter):
|
||||||
|
def __init__(self, **opts):
|
||||||
|
opts['type'] = 'bool'
|
||||||
|
opts['value'] = True
|
||||||
|
pTypes.GroupParameter.__init__(self, **opts)
|
||||||
|
|
||||||
|
self.addChild({'name': 'A = 1/B', 'type': 'float', 'value': 7, 'suffix': 'Hz', 'siPrefix': True})
|
||||||
|
self.addChild({'name': 'B = 1/A', 'type': 'float', 'value': 1/7., 'suffix': 's', 'siPrefix': True})
|
||||||
|
self.a = self.param('A = 1/B')
|
||||||
|
self.b = self.param('B = 1/A')
|
||||||
|
self.a.sigValueChanged.connect(self.aChanged)
|
||||||
|
self.b.sigValueChanged.connect(self.bChanged)
|
||||||
|
|
||||||
|
def aChanged(self):
|
||||||
|
self.b.setValue(1.0 / self.a.value(), blockSignal=self.bChanged)
|
||||||
|
|
||||||
|
def bChanged(self):
|
||||||
|
self.a.setValue(1.0 / self.b.value(), blockSignal=self.aChanged)
|
||||||
|
|
||||||
|
|
||||||
|
## test add/remove
|
||||||
|
## this group includes a menu allowing the user to add new parameters into its child list
|
||||||
|
class ScalableGroup(pTypes.GroupParameter):
|
||||||
|
def __init__(self, **opts):
|
||||||
|
opts['type'] = 'group'
|
||||||
|
opts['addText'] = "Add"
|
||||||
|
opts['addList'] = ['str', 'float', 'int']
|
||||||
|
pTypes.GroupParameter.__init__(self, **opts)
|
||||||
|
|
||||||
|
def addNew(self, typ):
|
||||||
|
val = {
|
||||||
|
'str': '',
|
||||||
|
'float': 0.0,
|
||||||
|
'int': 0
|
||||||
|
}[typ]
|
||||||
|
self.addChild(dict(name="ScalableParam %d" % (len(self.childs)+1), type=typ, value=val, removable=True, renamable=True))
|
||||||
|
|
||||||
|
|
||||||
|
## test column spanning (widget sub-item that spans all columns)
|
||||||
|
class TextParameterItem(pTypes.WidgetParameterItem):
|
||||||
|
def __init__(self, param, depth):
|
||||||
|
pTypes.WidgetParameterItem.__init__(self, param, depth)
|
||||||
|
self.subItem = QtGui.QTreeWidgetItem()
|
||||||
|
self.addChild(self.subItem)
|
||||||
|
|
||||||
|
def treeWidgetChanged(self):
|
||||||
|
self.treeWidget().setFirstItemColumnSpanned(self.subItem, True)
|
||||||
|
self.treeWidget().setItemWidget(self.subItem, 0, self.textBox)
|
||||||
|
self.setExpanded(True)
|
||||||
|
|
||||||
|
def makeWidget(self):
|
||||||
|
self.textBox = QtGui.QTextEdit()
|
||||||
|
self.textBox.setMaximumHeight(100)
|
||||||
|
self.textBox.value = lambda: str(self.textBox.toPlainText())
|
||||||
|
self.textBox.setValue = self.textBox.setPlainText
|
||||||
|
self.textBox.sigChanged = self.textBox.textChanged
|
||||||
|
return self.textBox
|
||||||
|
|
||||||
|
class TextParameter(Parameter):
|
||||||
|
type = 'text'
|
||||||
|
itemClass = TextParameterItem
|
||||||
|
|
||||||
|
registerParameterType('text', TextParameter)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
params = [
|
||||||
|
{'name': 'Basic parameter data types', 'type': 'group', 'children': [
|
||||||
|
{'name': 'Integer', 'type': 'int', 'value': 10},
|
||||||
|
{'name': 'Float', 'type': 'float', 'value': 10.5, 'step': 0.1},
|
||||||
|
{'name': 'String', 'type': 'str', 'value': "hi"},
|
||||||
|
{'name': 'List', 'type': 'list', 'values': [1,2,3], 'value': 2},
|
||||||
|
{'name': 'Named List', 'type': 'list', 'values': {"one": 1, "two": 2, "three": 3}, 'value': 2},
|
||||||
|
{'name': 'Boolean', 'type': 'bool', 'value': True, 'tip': "This is a checkbox"},
|
||||||
|
{'name': 'Color', 'type': 'color', 'value': "FF0", 'tip': "This is a color button"},
|
||||||
|
{'name': 'Subgroup', 'type': 'group', 'children': [
|
||||||
|
{'name': 'Sub-param 1', 'type': 'int', 'value': 10},
|
||||||
|
{'name': 'Sub-param 2', 'type': 'float', 'value': 1.2e6},
|
||||||
|
]},
|
||||||
|
]},
|
||||||
|
{'name': 'Numerical Parameter Options', 'type': 'group', 'children': [
|
||||||
|
{'name': 'Units + SI prefix', 'type': 'float', 'value': 1.2e-6, 'step': 1e-6, 'siPrefix': True, 'suffix': 'V'},
|
||||||
|
{'name': 'Limits (min=7;max=15)', 'type': 'int', 'value': 11, 'limits': (7, 15), 'default': -6},
|
||||||
|
{'name': 'DEC stepping', 'type': 'float', 'value': 1.2e6, 'dec': True, 'step': 1, 'siPrefix': True, 'suffix': 'Hz'},
|
||||||
|
|
||||||
|
]},
|
||||||
|
{'name': 'Extra Parameter Options', 'type': 'group', 'children': [
|
||||||
|
{'name': 'Read-only', 'type': 'float', 'value': 1.2e6, 'siPrefix': True, 'suffix': 'Hz', 'readonly': True},
|
||||||
|
{'name': 'Renamable', 'type': 'float', 'value': 1.2e6, 'siPrefix': True, 'suffix': 'Hz', 'renamable': True},
|
||||||
|
{'name': 'Removable', 'type': 'float', 'value': 1.2e6, 'siPrefix': True, 'suffix': 'Hz', 'removable': True},
|
||||||
|
]},
|
||||||
|
ComplexParameter(name='Custom parameter group (reciprocal values)'),
|
||||||
|
ScalableGroup(name="Expandable Parameter Group", children=[
|
||||||
|
{'name': 'ScalableParam 1', 'type': 'str', 'value': "default param 1"},
|
||||||
|
{'name': 'ScalableParam 2', 'type': 'str', 'value': "default param 2"},
|
||||||
|
]),
|
||||||
|
{'name': 'Custom parameter class (text box)', 'type': 'text', 'value': 'Some text...'},
|
||||||
|
]
|
||||||
|
|
||||||
|
## Create tree of Parameter objects
|
||||||
|
p = Parameter(name='params', type='group', children=params)
|
||||||
|
|
||||||
|
## If anything changes in the tree, print a message
|
||||||
|
def change(param, changes):
|
||||||
|
print("tree changes:")
|
||||||
|
for param, change, data in changes:
|
||||||
|
path = p.childPath(param)
|
||||||
|
if path is not None:
|
||||||
|
childName = '.'.join(path)
|
||||||
|
else:
|
||||||
|
childName = param.name()
|
||||||
|
print(' parameter: %s'% childName)
|
||||||
|
print(' change: %s'% change)
|
||||||
|
print(' data: %s'% str(data))
|
||||||
|
print(' ----------')
|
||||||
|
|
||||||
|
p.sigTreeStateChanged.connect(change)
|
||||||
|
|
||||||
|
## Create two ParameterTree widgets, both accessing the same data
|
||||||
|
t = ParameterTree()
|
||||||
|
t.setParameters(p, showTop=False)
|
||||||
|
t.show()
|
||||||
|
t.resize(400,600)
|
||||||
|
t2 = ParameterTree()
|
||||||
|
t2.setParameters(p, showTop=False)
|
||||||
|
t2.show()
|
||||||
|
t2.resize(400,600)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Start Qt event loop unless running in interactive mode or using pyside.
|
||||||
|
import sys
|
||||||
|
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
|
||||||
|
QtGui.QApplication.instance().exec_()
|
@ -131,11 +131,16 @@ class Parameter(QtCore.QObject):
|
|||||||
return name
|
return name
|
||||||
|
|
||||||
def childPath(self, child):
|
def childPath(self, child):
|
||||||
"""Return the path of parameter names from self to child."""
|
"""
|
||||||
|
Return the path of parameter names from self to child.
|
||||||
|
If child is not a (grand)child of self, return None.
|
||||||
|
"""
|
||||||
path = []
|
path = []
|
||||||
while child is not self:
|
while child is not self:
|
||||||
path.insert(0, child.name())
|
path.insert(0, child.name())
|
||||||
child = child.parent()
|
child = child.parent()
|
||||||
|
if child is None:
|
||||||
|
return None
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def setValue(self, value, blockSignal=None):
|
def setValue(self, value, blockSignal=None):
|
||||||
|
@ -1,132 +0,0 @@
|
|||||||
## tests for ParameterTree
|
|
||||||
|
|
||||||
## make sure pyqtgraph is in path
|
|
||||||
import sys,os
|
|
||||||
md = os.path.abspath(os.path.dirname(__file__))
|
|
||||||
sys.path.append(os.path.join(md, '..', '..'))
|
|
||||||
|
|
||||||
from pyqtgraph.Qt import QtCore, QtGui
|
|
||||||
import collections
|
|
||||||
app = QtGui.QApplication([])
|
|
||||||
import pyqtgraph.parametertree.parameterTypes as pTypes
|
|
||||||
from pyqtgraph.parametertree import Parameter, ParameterTree, ParameterItem, registerParameterType
|
|
||||||
|
|
||||||
|
|
||||||
## test subclassing parameters
|
|
||||||
## This parameter automatically generates two child parameters which are always reciprocals of each other
|
|
||||||
class ComplexParameter(Parameter):
|
|
||||||
def __init__(self, **opts):
|
|
||||||
opts['type'] = 'bool'
|
|
||||||
opts['value'] = True
|
|
||||||
Parameter.__init__(self, **opts)
|
|
||||||
|
|
||||||
self.addChild({'name': 'A = 1/B', 'type': 'float', 'value': 7, 'suffix': 'Hz', 'siPrefix': True})
|
|
||||||
self.addChild({'name': 'B = 1/A', 'type': 'float', 'value': 1/7., 'suffix': 's', 'siPrefix': True})
|
|
||||||
self.a = self.param('A = 1/B')
|
|
||||||
self.b = self.param('B = 1/A')
|
|
||||||
self.a.sigValueChanged.connect(self.aChanged)
|
|
||||||
self.b.sigValueChanged.connect(self.bChanged)
|
|
||||||
|
|
||||||
def aChanged(self):
|
|
||||||
self.b.setValue(1.0 / self.a.value(), blockSignal=self.bChanged)
|
|
||||||
|
|
||||||
def bChanged(self):
|
|
||||||
self.a.setValue(1.0 / self.b.value(), blockSignal=self.aChanged)
|
|
||||||
|
|
||||||
|
|
||||||
## test add/remove
|
|
||||||
## this group includes a menu allowing the user to add new parameters into its child list
|
|
||||||
class ScalableGroup(pTypes.GroupParameter):
|
|
||||||
def __init__(self, **opts):
|
|
||||||
opts['type'] = 'group'
|
|
||||||
opts['addText'] = "Add"
|
|
||||||
opts['addList'] = ['str', 'float', 'int']
|
|
||||||
pTypes.GroupParameter.__init__(self, **opts)
|
|
||||||
|
|
||||||
def addNew(self, typ):
|
|
||||||
val = {
|
|
||||||
'str': '',
|
|
||||||
'float': 0.0,
|
|
||||||
'int': 0
|
|
||||||
}[typ]
|
|
||||||
self.addChild(dict(name="ScalableParam %d" % (len(self.childs)+1), type=typ, value=val, removable=True, renamable=True))
|
|
||||||
|
|
||||||
|
|
||||||
## test column spanning (widget sub-item that spans all columns)
|
|
||||||
class TextParameterItem(pTypes.WidgetParameterItem):
|
|
||||||
def __init__(self, param, depth):
|
|
||||||
pTypes.WidgetParameterItem.__init__(self, param, depth)
|
|
||||||
self.subItem = QtGui.QTreeWidgetItem()
|
|
||||||
self.addChild(self.subItem)
|
|
||||||
|
|
||||||
def treeWidgetChanged(self):
|
|
||||||
self.treeWidget().setFirstItemColumnSpanned(self.subItem, True)
|
|
||||||
self.treeWidget().setItemWidget(self.subItem, 0, self.textBox)
|
|
||||||
self.setExpanded(True)
|
|
||||||
|
|
||||||
def makeWidget(self):
|
|
||||||
self.textBox = QtGui.QTextEdit()
|
|
||||||
self.textBox.setMaximumHeight(100)
|
|
||||||
self.textBox.value = lambda: str(self.textBox.toPlainText())
|
|
||||||
self.textBox.setValue = self.textBox.setPlainText
|
|
||||||
self.textBox.sigChanged = self.textBox.textChanged
|
|
||||||
return self.textBox
|
|
||||||
|
|
||||||
class TextParameter(Parameter):
|
|
||||||
type = 'text'
|
|
||||||
itemClass = TextParameterItem
|
|
||||||
|
|
||||||
registerParameterType('text', TextParameter)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
params = [
|
|
||||||
{'name': 'Group 0', 'type': 'group', 'children': [
|
|
||||||
{'name': 'Param 1', 'type': 'int', 'value': 10},
|
|
||||||
{'name': 'Param 2', 'type': 'float', 'value': 10},
|
|
||||||
]},
|
|
||||||
{'name': 'Group 1', 'type': 'group', 'children': [
|
|
||||||
{'name': 'Param 1.1', 'type': 'float', 'value': 1.2e-6, 'dec': True, 'siPrefix': True, 'suffix': 'V'},
|
|
||||||
{'name': 'Param 1.2', 'type': 'float', 'value': 1.2e6, 'dec': True, 'siPrefix': True, 'suffix': 'Hz'},
|
|
||||||
{'name': 'Group 1.3', 'type': 'group', 'children': [
|
|
||||||
{'name': 'Param 1.3.1', 'type': 'int', 'value': 11, 'limits': (-7, 15), 'default': -6},
|
|
||||||
{'name': 'Param 1.3.2', 'type': 'float', 'value': 1.2e6, 'dec': True, 'siPrefix': True, 'suffix': 'Hz', 'readonly': True},
|
|
||||||
]},
|
|
||||||
{'name': 'Param 1.4', 'type': 'str', 'value': "hi"},
|
|
||||||
{'name': 'Param 1.5', 'type': 'list', 'values': [1,2,3], 'value': 2},
|
|
||||||
{'name': 'Param 1.6', 'type': 'list', 'values': {"one": 1, "two": 2, "three": 3}, 'value': 2},
|
|
||||||
ComplexParameter(name='ComplexParam'),
|
|
||||||
ScalableGroup(name="ScalableGroup", children=[
|
|
||||||
{'name': 'ScalableParam 1', 'type': 'str', 'value': "hi"},
|
|
||||||
{'name': 'ScalableParam 2', 'type': 'str', 'value': "hi"},
|
|
||||||
|
|
||||||
])
|
|
||||||
]},
|
|
||||||
{'name': 'Param 5', 'type': 'bool', 'value': True, 'tip': "This is a checkbox"},
|
|
||||||
{'name': 'Param 6', 'type': 'color', 'value': "FF0", 'tip': "This is a color button. It cam be renamed.", 'renamable': True},
|
|
||||||
{'name': 'TextParam', 'type': 'text', 'value': 'Some text...'},
|
|
||||||
]
|
|
||||||
|
|
||||||
#p = pTypes.ParameterSet("params", params)
|
|
||||||
p = Parameter(name='params', type='group', children=params)
|
|
||||||
def change(param, changes):
|
|
||||||
print("tree changes:")
|
|
||||||
for param, change, data in changes:
|
|
||||||
print(" [" + '.'.join(p.childPath(param))+ "] ", change, data)
|
|
||||||
|
|
||||||
p.sigTreeStateChanged.connect(change)
|
|
||||||
|
|
||||||
|
|
||||||
t = ParameterTree()
|
|
||||||
t.setParameters(p, showTop=False)
|
|
||||||
t.show()
|
|
||||||
t.resize(400,600)
|
|
||||||
t2 = ParameterTree()
|
|
||||||
t2.setParameters(p, showTop=False)
|
|
||||||
t2.show()
|
|
||||||
t2.resize(400,600)
|
|
||||||
|
|
||||||
import sys
|
|
||||||
if sys.flags.interactive == 0:
|
|
||||||
app.exec_()
|
|
@ -348,6 +348,7 @@ class GroupParameterItem(ParameterItem):
|
|||||||
|
|
||||||
def treeWidgetChanged(self):
|
def treeWidgetChanged(self):
|
||||||
ParameterItem.treeWidgetChanged(self)
|
ParameterItem.treeWidgetChanged(self)
|
||||||
|
self.treeWidget().setFirstItemColumnSpanned(self, True)
|
||||||
if self.addItem is not None:
|
if self.addItem is not None:
|
||||||
self.treeWidget().setItemWidget(self.addItem, 0, self.addWidgetBox)
|
self.treeWidget().setItemWidget(self.addItem, 0, self.addWidgetBox)
|
||||||
self.treeWidget().setFirstItemColumnSpanned(self.addItem, True)
|
self.treeWidget().setFirstItemColumnSpanned(self.addItem, True)
|
||||||
|
Loading…
Reference in New Issue
Block a user