Easy Chart : pen control panel

Hello everybody,

Is there any way to change the pen control panel position in an easy chart ? I would like to put it on the right of my chart but i haven’t figured out how to do yet.
Thanks in advance.

1 Like

Unfortunately, there is not way to change the position of the pen control panel, although you can add cell update bindings to the Tag Pens dataset to allow other components to hide, show, enable, or disable the pens.

1 Like

@adam.morales

I have a similar issue. Want to relocate the checkbox of pen to be closer to the chart, but did not find the related options.

For the workaround, so do we still need to create an independent checkbox group and bind them to the visiable column of pen dataset?

Hey all,

I’m a little late to the party here – just encountered the same issue as well, thought I would share our solution…
It seems as though pen control is a secondary jcomponent that sits under the easychart jpanel (e.g. if you were to call self.getComponents(), you would get two elements:

array(java.awt.Component, [javax.swing.JPanel[,0,0,400x442,layout=java.awt.BorderLayout,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@325d8ca0,flags=16777217,maximumSize=,minimumSize=,preferredSize=], com.inductiveautomation.factorypmi.application.components.PMIEasyChart$PenPanel[,0,442,400x48,layout=java.awt.BorderLayout,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@49a1e3ed,flags=16777217,maximumSize=,minimumSize=,preferredSize=]])

…that second element is the pen control panel (PMIEasyChart$PenPanel).

Luckily – you can use the ‘configureChart’ extension function to modify the layout position of this component prior to rendering (the base jpanel uses borderlayout for easychart)… I wanted the pen controls placed at the bottom of the screen, so that we could maximize the horizontal space for the trend area:

def configureChart(self, chart):
	"""
	Provides an opportunity to perform further chart configuration via
	scripting. Doesn't return anything.

	Arguments:
		self: A reference to the component that is invoking this function.
		chart: A JFreeChart object. Refer to the JFreeChart documentation for
		       API details.
	"""
	from java.awt import BorderLayout
	from com.inductiveautomation.factorypmi.application.components.PMIEasyChart import PenPanel
	for c in self.getComponents(): # iterate over the jcomponents
		if isinstance(c, PenPanel): # find the pen control panel
			self.remove(c) # remove it from the layout manager
			self.add(c, BorderLayout.PAGE_END) # add it back to the bottom
			self.validate() # repaint!

Voila – pen controls to the bottom :slight_smile:
modified%20easychart

4 Likes

Thank you very much for this help ! I’m lacking of knoledge with all the java component properties but it is very interesting because it adds many functionnalities to ignition.

I’m wondering if the control pen panel can display the pens horizontally and not vertically as it is ?
I’m looking for into the javadocs bu i didn’t figure out which property has to be changed.

Hi Pascal – I imagine so… guessing that the jcomponent for the pen control also has it’s own layout manager for the container…

Maybe take a look at the com.inductiveautomation.factorypmi.application.components.PMIEasyChart$PenPanel object.

e.g.

from com.inductiveautomation.factorypmi.application.components.PMIEasyChart import PenPanel

pp = PenPanel

print(dir(pp))

outputs this:

['ABORT', 'ALLBITS', 'AccessibleJComponent', 'BOTTOM_ALIGNMENT', 'BaselineResizeBehavior', 'CENTER_ALIGNMENT', 'ERROR', 'FRAMEBITS', 'HEIGHT', 'LEFT_ALIGNMENT', 'PROPERTIES', 'PenControl', 'RIGHT_ALIGNMENT', 'SOMEBITS', 'TOOL_TIP_TEXT_KEY', 'TOP_ALIGNMENT', 'UI', 'UIClassID', 'UNDEFINED_CONDITION', 'WHEN_ANCESTOR_OF_FOCUSED_COMPONENT', 'WHEN_FOCUSED', 'WHEN_IN_FOCUSED_WINDOW', 'WIDTH', '__class__', '__copy__', '__deepcopy__', '__delattr__', '__doc__', '__ensure_finalizer__', '__eq__', '__format__', '__getattribute__', '__hash__', '__init__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__subclasshook__', '__unicode__', 'accessibleContext', 'action', 'actionMap', 'actionPerformed', 'add', 'addAncestorListener', 'addComponentListener', 'addContainerListener', 'addFocusListener', 'addHierarchyBoundsListener', 'addHierarchyListener', 'addInputMethodListener', 'addKeyListener', 'addMouseListener', 'addMouseMotionListener', 'addMouseWheelListener', 'addNotify', 'addPropertyChangeListener', 'addVetoableChangeListener', 'alignmentX', 'alignmentY', 'ancestorAdded', 'ancestorListener', 'ancestorListeners', 'ancestorMoved', 'ancestorRemoved', 'ancestorResized', 'applyComponentOrientation', 'areFocusTraversalKeysSet', 'autoscrolls', 'background', 'backgroundSet', 'baselineResizeBehavior', 'border', 'bounds', 'caretPositionChanged', 'checkBoxes', 'checkImage', 'class', 'colorModel', 'componentAdded', 'componentCount', 'componentHidden', 'componentListener', 'componentListeners', 'componentMoved', 'componentOrientation', 'componentPopupMenu', 'componentRemoved', 'componentResized', 'componentShown', 'components', 'computeVisibleRect', 'containerListener', 'containerListeners', 'contains', 'countComponents', 'createGUI', 'createImage', 'createToolTip', 'createVolatileImage', 'cursor', 'cursorSet', 'debugGraphicsOptions', 'deliverEvent', 'disable', 'dispatchEvent', 'displayable', 'doLayout', 'doubleBuffered', 'dropTarget', 'enable', 'enableInputMethods', 'enabled', 'equals', 'findComponentAt', 'firePropertyChange', 'focusCycleRoot', 'focusCycleRootAncestor', 'focusGained', 'focusListener', 'focusListeners', 'focusLost', 'focusOwner', 'focusTraversable', 'focusTraversalKeysEnabled', 'focusTraversalPolicy', 'focusTraversalPolicyProvider', 'focusTraversalPolicySet', 'focusable', 'font', 'fontSet', 'foreground', 'foregroundSet', 'getAccessibleContext', 'getActionForKeyStroke', 'getActionMap', 'getAlignmentX', 'getAlignmentY', 'getAncestorListeners', 'getAutoscrolls', 'getBackground', 'getBaseline', 'getBaselineResizeBehavior', 'getBorder', 'getBounds', 'getCheckBoxes', 'getClass', 'getClientProperty', 'getColorModel', 'getComponent', 'getComponentAt', 'getComponentCount', 'getComponentListeners', 'getComponentOrientation', 'getComponentPopupMenu', 'getComponentZOrder', 'getComponents', 'getConditionForKeyStroke', 'getContainerListeners', 'getCursor', 'getDebugGraphicsOptions', 'getDefaultLocale', 'getDropTarget', 'getFocusCycleRootAncestor', 'getFocusListeners', 'getFocusTraversalKeys', 'getFocusTraversalKeysEnabled', 'getFocusTraversalPolicy', 'getFont', 'getFontMetrics', 'getForeground', 'getGraphics', 'getGraphicsConfiguration', 'getHeight', 'getHierarchyBoundsListeners', 'getHierarchyListeners', 'getIgnoreRepaint', 'getInheritsPopupMenu', 'getInputContext', 'getInputMap', 'getInputMethodListeners', 'getInputMethodRequests', 'getInputVerifier', 'getInsets', 'getKeyListeners', 'getLayout', 'getListeners', 'getLocale', 'getLocation', 'getLocationOnScreen', 'getMaximumSize', 'getMinimumSize', 'getMouseListeners', 'getMouseMotionListeners', 'getMousePosition', 'getMouseWheelListeners', 'getName', 'getNextFocusableComponent', 'getParent', 'getPopupLocation', 'getPreferredSize', 'getPropertyChangeListeners', 'getRegisteredKeyStrokes', 'getRootPane', 'getSize', 'getToolTipLocation', 'getToolTipText', 'getToolkit', 'getTopLevelAncestor', 'getTransferHandler', 'getTreeLock', 'getUI', 'getUIClassID', 'getVerifyInputWhenFocusTarget', 'getVetoableChangeListeners', 'getVisibleRect', 'getWidth', 'getX', 'getY', 'gotFocus', 'grabFocus', 'graphics', 'graphicsConfiguration', 'handleEvent', 'hasFocus', 'hashCode', 'height', 'hide', 'hierarchyBoundsListener', 'hierarchyBoundsListeners', 'hierarchyChanged', 'hierarchyListener', 'hierarchyListeners', 'ignoreRepaint', 'imageUpdate', 'inheritsPopupMenu', 'inputContext', 'inputMap', 'inputMethodListener', 'inputMethodListeners', 'inputMethodRequests', 'inputMethodTextChanged', 'inputVerifier', 'insets', 'inside', 'invalidate', 'isAncestorOf', 'isBackgroundSet', 'isCursorSet', 'isDisplayable', 'isDoubleBuffered', 'isEnabled', 'isFocusCycleRoot', 'isFocusOwner', 'isFocusTraversable', 'isFocusTraversalPolicyProvider', 'isFocusTraversalPolicySet', 'isFocusable', 'isFontSet', 'isForegroundSet', 'isLightweight', 'isLightweightComponent', 'isManagingFocus', 'isMaximumSizeSet', 'isMinimumSizeSet', 'isOpaque', 'isOptimizedDrawingEnabled', 'isPaintingForPrint', 'isPaintingTile', 'isPreferredSizeSet', 'isRequestFocusEnabled', 'isShowing', 'isValid', 'isValidateRoot', 'isVisible', 'keyDown', 'keyListener', 'keyListeners', 'keyPressed', 'keyReleased', 'keyTyped', 'keyUp', 'layout', 'lightweight', 'list', 'locale', 'localeChanged', 'locate', 'location', 'locationOnScreen', 'lostFocus', 'managingFocus', 'maximumSize', 'maximumSizeSet', 'minimumSize', 'minimumSizeSet', 'mixingCutoutShape', 'mouseClicked', 'mouseDown', 'mouseDrag', 'mouseDragged', 'mouseEnter', 'mouseEntered', 'mouseExit', 'mouseExited', 'mouseListener', 'mouseListeners', 'mouseMotionListener', 'mouseMotionListeners', 'mouseMove', 'mouseMoved', 'mousePosition', 'mousePressed', 'mouseReleased', 'mouseUp', 'mouseWheelListener', 'mouseWheelListeners', 'mouseWheelMoved', 'move', 'name', 'nextFocus', 'nextFocusableComponent', 'notify', 'notifyAll', 'opaque', 'optimizedDrawingEnabled', 'paint', 'paintAll', 'paintComponents', 'paintImmediately', 'paintingForPrint', 'paintingTile', 'parent', 'postEvent', 'preferredSize', 'preferredSizeSet', 'prepareImage', 'print', 'printAll', 'printComponents', 'propertyChange', 'propertyChangeListener', 'propertyChangeListeners', 'putClientProperty', 'recreateGUI', 'registerKeyboardAction', 'registeredKeyStrokes', 'remove', 'removeAll', 'removeAncestorListener', 'removeComponentListener', 'removeContainerListener', 'removeFocusListener', 'removeHierarchyBoundsListener', 'removeHierarchyListener', 'removeInputMethodListener', 'removeKeyListener', 'removeMouseListener', 'removeMouseMotionListener', 'removeMouseWheelListener', 'removeNotify', 'removePropertyChangeListener', 'removeVetoableChangeListener', 'repaint', 'requestDefaultFocus', 'requestFocus', 'requestFocusEnabled', 'requestFocusInWindow', 'resetKeyboardActions', 'reshape', 'resize', 'revalidate', 'rootPane', 'scrollRectToVisible', 'setActionMap', 'setAlignmentX', 'setAlignmentY', 'setAutoscrolls', 'setBackground', 'setBorder', 'setBounds', 'setComponentOrientation', 'setComponentPopupMenu', 'setComponentZOrder', 'setCursor', 'setDebugGraphicsOptions', 'setDefaultLocale', 'setDoubleBuffered', 'setDropTarget', 'setEnabled', 'setFocusCycleRoot', 'setFocusTraversalKeys', 'setFocusTraversalKeysEnabled', 'setFocusTraversalPolicy', 'setFocusTraversalPolicyProvider', 'setFocusable', 'setFont', 'setForeground', 'setIgnoreRepaint', 'setInheritsPopupMenu', 'setInputMap', 'setInputVerifier', 'setLayout', 'setLocale', 'setLocation', 'setMaximumSize', 'setMinimumSize', 'setMixingCutoutShape', 'setName', 'setNextFocusableComponent', 'setOpaque', 'setPreferredSize', 'setRequestFocusEnabled', 'setSize', 'setToolTipText', 'setTransferHandler', 'setUI', 'setVerifyInputWhenFocusTarget', 'setVisible', 'show', 'showing', 'size', 'toString', 'toolTipText', 'toolkit', 'topLevelAncestor', 'transferFocus', 'transferFocusBackward', 'transferFocusDownCycle', 'transferFocusUpCycle', 'transferHandler', 'treeLock', 'unregisterKeyboardAction', 'update', 'updateUI', 'valid', 'validate', 'validateRoot', 'verifyInputWhenFocusTarget', 'vetoableChange', 'vetoableChangeListener', 'vetoableChangeListeners', 'visible', 'visibleRect', 'wait', 'width', 'x', 'y']

so you should be able to do a “.setLayout()” on that component as well… (not sure if the pen/checkboxes are embedded directly under this jcomponent) – you might have to do some testing/trial & error

Kind Regards,

-Paul

That is what i did last week but when it did’nt work. I used setLayout(FlowLayout()) but the output is always the same.
I’ll have to dig that up.

Thanks anyways !

Hey Pascal,

I’m thinking that there are a few components embedded within the pen control… one JPanel, and JScrollPane – the latter, I presume is to resize based on the tag count?

I would imagine that you would need to change/update the layout manager for the JScrollPane… e.g.

from java.awt import BorderLayout, FlowLayout
	from javax.swing import JScrollPane
	from com.inductiveautomation.factorypmi.application.components.PMIEasyChart import PenPanel
	for c in self.getComponents(): # iterate over the jcomponents
		if isinstance(c, PenPanel): # find the pen control panel
			print(dir(c))

			for ch in c.getComponents(): # inspect the children of the pen control
				if isinstance(ch, JScrollPane): # find the tag list portion of the pen control
					pass
					#do something with this layout manager?
			self.remove(c) # remove it from the layout manager
			self.add(c, BorderLayout.PAGE_END) # add it back to the bottom
			self.validate() # repaint!

Hope this helps!

-Paul