Moving label component as per changing value

hi,

basically i have a one vision chart component and data is continously coming from the SQL database.

i bind this graph with sql query:
image

i took a label component beside the graph as shown below:
image

i bind these labels with sql query as per their reference Column value. sql query is:

i want to move these component whenever the value of UCL, LCL,X Bar,LSL,USL is change and lines get fluctuate in graph ,so these component will also move and set in front of lines as per like settle now.

please guide me.

please guide me

1 Like

You'll probably have a much easier time trying to do this within the chart itself, using some marker class from JFreeChart. There's some examples on the forums.

Moving the components could be done with system.gui.transform, but matching the locations in the parent window with the relative locations within the chart would be tricky and probably unreliable. That's why I'd suggest doing it in the chart directly.

1 Like

I've done a few examples of this sort of thing that could possibly help:
Example 1: Here I use xy annotation to make custom xtrace labels that move with the xtrace crosshair
Example 2: In this example, I place actual PMILabels in the chart, so they correspond with a varied bar position. Later in the thread, after the OP changed chart types, I also do another xy annotation example.

My guess is that the actual labels will be a better approach for what you are trying to do, since it appears that you are wanting the labels to be outside of the plot.

1 Like

As i checked example 1, i am stuck how to set chart component mode to x trace so after that i can get the label on my chart like this:

and how to get this vertical tracing line.
please help me

The typical way to do this is to right click on the chart, and in the popup menu that appears, select MODE-->X-trace. Then, clicking anywhere on the chart will generate the crosshair. I'm certain that it could be scripted to automatically happen though if that is what you are wanting to do. With this approach, there would be no way to position the labels outside of the plot, although the labels could easily be made to look like the ones you depict above, and they could be positioned all the way to the left of the visible domain.

If you're just wanting labels to appear in the xtrace, no scripting is needed. The above example replaces the normal labels with custom ones, so the real benefit of the example is how to make custom labels and position them wherever you want. For most people though, I believe the the normal xtrace labels are what is wanted.

Yes i needed the custom one as like above.so i can check the value in label at any point in the chart.

This sort of thing is more or less trivial for me to do, and I have no problem typing up a specific example for your usage case. Just to be clear, you are wanting xy text annotations that look like this:
image
...that are located on the right side of the visible plot no matter what mode the user selects?

Just remember that this approach doesn't work outside of the plot, so with this approach, your chart will end up looking like this:
image

Is this close enough to what you are wanting? If so, is this an Easy Chart or a Basic Chart?

yes this is suitable ,please guide me how to do that and its a basic chart which i used

The following works in my test chart:
Step 1: Create a custom method on the chart called setLabels with no parameters
Step 2: Add this code to the custom method:

#def setLabels(self):
	from org.jfree.chart.annotations import XYTextAnnotation
	from java.awt.font import FontRenderContext, TextLayout
	from java.awt import Color, Font
	def getLabelText(row, column, data):
		pointer = u' ▶'
		penName = data.getColumnName(column)
		penValue = data.getValueAt(row, column)
		text = penName + ' (' +str(penValue) + ')' + pointer
		return text
	def getLabelX(layout):
		domainAxis = self.chart.plot.domainAxis
		upperBound = domainAxis.upperBound
		domainWidth = domainAxis.upperBound - domainAxis.lowerBound
		chartWidth = self.chartRenderingInfo.chartArea.width
		pixelOffset = layout.bounds.width
		offsetRatio = pixelOffset/float(chartWidth)
		domainOffset = domainWidth * offsetRatio
		return (upperBound - domainOffset)
	def getMaxVisibleDomain(plot, data):
		upperBound = plot.domainAxis.upperBound
		sortedData = system.dataset.sort(data, 0, False)
		for row in range(sortedData.rowCount):
			domainPoint = sortedData.getValueAt(row, 0).getTime()
			if domainPoint  < upperBound:
				return domainPoint
	def getLabels(plot, labelFont):
		data = self.Data
		maxVisibleDomain = getMaxVisibleDomain(plot, data)
		headers = ['text', 'x', 'y']
		labelData = []
		for row in range(data.rowCount):
			if data.getValueAt(row, 0).getTime() == maxVisibleDomain:
				for column in range(1, data.columnCount):
					text = getLabelText(row, column, data)
					layout = TextLayout(text, labelFont, FontRenderContext(None, False, False))
					x = getLabelX(layout)
					y = data.getValueAt(row, column)
					labelData.append([text, x, y])
		labels = system.dataset.toDataSet(headers, labelData)
		return labels
	def setLabels(plot):
		labelFont = Font(Font.MONOSPACED, Font.BOLD, 14)
		labels = getLabels(plot, labelFont)
		for row in range(labels.rowCount):
			text = labels.getValueAt(row, 0)
			x = labels.getValueAt(row, 1)
			y = labels.getValueAt(row, 2)
			label = XYTextAnnotation(text, x, y)
			label.setPaint(Color.white)
			label.setFont(labelFont)
			plot.addAnnotation(label)
	plot = self.chart.plot
	for label in plot.getAnnotations():
		if isinstance(label, XYTextAnnotation):
			plot.removeAnnotation(label)
	setLabels(plot)

In the mouseReleased event handler, call the custom method using event.source.setLabels()

In the propertyChange event handler, you can call the custom method like this:

if event.propertyName == 'componentRunning':
	event.source.setLabels()

If you need to run this from the configureChart extension function, call it this way:

def configureChart(self, chart):
	def setLabels():
		self.setLabels()
	system.util.invokeLater(setLabels)

Here is the result:
image

If you get stuck or need clarification, here is the test window I created to develop this:
testWindow.zip (11.8 KB)

just import it, and you will be able to see how everything is set up

2 Likes

If you don't want to go through all of that hassle, you might want to try my NoteChart module. It has a completely reworked X-Trace function, that includes delivering a one-row dataset of pen values at the, and offering extension methods to replace the normal X-Trace value rendering. You could simply return an empty string for the regular labels, and use the dataset to drive your statically-positioned labels.

1 Like

Hi Justin,

first its not working in my side when i implemented the same process as u suggested me,it seems nothing happen.Even the label is not showing on chart.
Another thing is that in your window when i run that if i clicked on some another place of process temp line, nothing happens the label remains there at the original place.its not moving at anywhere.

like if i want to click on any point of process temp line,it must show the value of process temp there at the position but it quite stick there and shows same value at the same position, not moving anywhere
test12.zip (15.6 KB)
check this window

What you are describing in this sentence is xtrace. No modification to the chart is needed for this. You can use the getXTraceLabel extension function to modify your label however you want. In your case:

#def getXTraceLabel(self, chart, penName, yValue):
	return penName + ' (' + str(yValue) + ')' + u' ▶'

In the example you uploaded, the labels are showing, but the paint color was set to white, so they could not be seen on the white background. [I wrote the script this way because your original post depicted a black background with white labels] I changed the label paint color to black and this was the result:
image

In any case, the proof of concept has been provided. Any further functionality is possible; it will simply require further development on your end.