# -*- 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 os import initExample ## Add path to library (just for examples; you do not need this) import pyqtgraph as pg from pyqtgraph.Qt import QtCore, QtGui app = pg.mkQApp("Parameter Tree Example") 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)) 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, 'finite': False}, {'name': 'String', 'type': 'str', 'value': "hi", 'tip': 'Well hello'}, {'name': 'Checklist', 'type': 'checklist', 'limits': [1,2,3], 'value': 2}, {'name': 'List', 'type': 'list', 'limits': [1,2,3], 'value': 2}, {'name': 'Named List', 'type': 'list', 'limits': {"one": 1, "two": "twosies", "three": [3,3,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': 'Gradient', 'type': 'colormap'}, {'name': 'Subgroup', 'type': 'group', 'children': [ {'name': 'Sub-param 1', 'type': 'int', 'value': 10}, {'name': 'Sub-param 2', 'type': 'float', 'value': 1.2e6}, ]}, {'name': 'Text Parameter', 'type': 'text', 'value': 'Some text...'}, {'name': 'Action Parameter', 'type': 'action', 'tip': 'Click me'}, ]}, {'name': 'Custom Parameter Options', 'type': 'group', 'children': [ {'name': 'Pen', 'type': 'pen', 'value': pg.mkPen(color=(255,0,0), width=2)}, {'name': 'Progress bar', 'type': 'progress', 'value':50, 'limits':(0,100)}, {'name': 'Slider', 'type': 'slider', 'value':50, 'limits':(0,100)}, {'name': 'Font', 'type': 'font', 'value':QtGui.QFont("Inter")}, {'name': 'Calendar', 'type': 'calendar', 'value':QtCore.QDate.currentDate().addMonths(1)}, {'name': 'Open python file', 'type': 'file', 'fileMode': 'ExistingFile', 'nameFilter': 'Python file (*.py);;', 'value': 'parametertree.py', 'relativeTo': os.getcwd(), 'options': ['DontResolveSymlinks']} ]}, {'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': 'Int suffix', 'type': 'int', 'value': 9, 'suffix': 'V'}, {'name': 'DEC stepping', 'type': 'float', 'value': 1.2e6, 'dec': True, 'step': 1, 'minStep': 1.0e-12, 'siPrefix': True, 'suffix': 'Hz'}, ]}, {'name': 'Save/Restore functionality', 'type': 'group', 'children': [ {'name': 'Save State', 'type': 'action'}, {'name': 'Restore State', 'type': 'action', 'children': [ {'name': 'Add missing items', 'type': 'bool', 'value': True}, {'name': 'Remove extra items', 'type': 'bool', 'value': True}, ]}, ]}, {'name': 'Extra Parameter Options', 'type': 'group', 'children': [ {'name': 'Read-only', 'type': 'float', 'value': 1.2e6, 'siPrefix': True, 'suffix': 'Hz', 'readonly': True}, {'name': 'Disabled', 'type': 'float', 'value': 1.2e6, 'siPrefix': True, 'suffix': 'Hz', 'enabled': False}, {'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}, ]}, {'name': 'Custom context menu', 'type': 'group', 'children': [ {'name': 'List contextMenu', 'type': 'float', 'value': 0, 'context': [ 'menu1', 'menu2' ]}, {'name': 'Dict contextMenu', 'type': 'float', 'value': 0, 'context': { 'changeName': 'Title', 'internal': 'What the user sees', }}, ]}, ComplexParameter(name='Custom parameter group (reciprocal values)'), ScalableGroup(name="Expandable Parameter Group", tip='Click to add children', children=[ {'name': 'ScalableParam 1', 'type': 'str', 'value': "default param 1"}, {'name': 'ScalableParam 2', 'type': 'str', 'value': "default param 2"}, ]), ] ## Create tree of Parameter objects p = Parameter.create(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) def valueChanging(param, value): print("Value changing (not finalized): %s %s" % (param, value)) # Too lazy for recursion: for child in p.children(): child.sigValueChanging.connect(valueChanging) for ch2 in child.children(): ch2.sigValueChanging.connect(valueChanging) def save(): global state state = p.saveState() def restore(): global state add = p['Save/Restore functionality', 'Restore State', 'Add missing items'] rem = p['Save/Restore functionality', 'Restore State', 'Remove extra items'] p.restoreState(state, addChildren=add, removeChildren=rem) p.param('Save/Restore functionality', 'Save State').sigActivated.connect(save) p.param('Save/Restore functionality', 'Restore State').sigActivated.connect(restore) ## Create two ParameterTree widgets, both accessing the same data t = ParameterTree() t.setParameters(p, showTop=False) t.setWindowTitle('pyqtgraph example: Parameter Tree') t2 = ParameterTree() t2.setParameters(p, showTop=False) win = QtGui.QWidget() layout = QtGui.QGridLayout() win.setLayout(layout) layout.addWidget(QtGui.QLabel("These are two views of the same data. They should always display the same values."), 0, 0, 1, 2) layout.addWidget(t, 1, 0, 1, 1) layout.addWidget(t2, 1, 1, 1, 1) win.show() ## test save/restore state = p.saveState() p.restoreState(state) compareState = p.saveState() assert pg.eq(compareState, state) if __name__ == '__main__': pg.exec()