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:
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