paradoxoff wrote:@liferiot
see
this thread.
@pfxo:
There is no easy way to achieve that. The JFreeChart just draws itself in the Rectangle provided in the draw-method. It doesn´t notice if the rectangle size between two calls has changed.
I have maybe found a solution for that. But I'm not sure whether it's a nice way. Whatever, I share my code, is written in Scala but Java coder should not have difficult to understand.
First, I created a
trait for the
XYPlot where all internals manage itself:
Code: Select all
package org.jfreex
package chart.plot
import java.awt.Graphics2D
import java.awt.geom. {
Point2D,
Rectangle2D
}
import org.jfree.chart.axis.AxisSpace
import org.jfree.chart.plot. {
PlotRenderingInfo,
PlotState,
XYPlot
}
/** Extends [[org.jfree.chart.plot.XYPlot]] with expandable axis.
*
* @author pfxo
*/
trait ExpandableXYPlot extends XYPlot {
override def draw(g2: Graphics2D,
area: Rectangle2D,
anchor: Point2D,
parentState: PlotState,
info: PlotRenderingInfo) {
if(area.getWidth <= Plot.MINIMUM_WIDTH_TO_DRAW ||
area.getHeight <= Plot.MINIMUM_HEIGHT_TO_DRAW)
return
val clonedArea = area.clone.asInstanceOf[Rectangle2D]
getInsets.trim(clonedArea)
val method = classOf[XYPlot].getDeclaredMethod("calculateAxisSpace",
classOf[Graphics2D],
classOf[Rectangle2D])
method.setAccessible(true)
val dataArea = method.invoke(this, g2, clonedArea).asInstanceOf[AxisSpace].shrink(clonedArea, null)
getAxisOffset.trim(dataArea)
if(dataArea.isEmpty)
return
if(lastDataArea.width != dataArea.getWidth) {
if(lastDataArea.width != -1.0 &&
lastDataArea.domainLength != -1.0)
getDomainAxis.setRange(
new org.jfree.data.Range(
getDomainAxis.getLowerBound,
getDomainAxis.getLowerBound + lastDataArea.domainLength /
lastDataArea.width * dataArea.getWidth), true, true)
lastDataArea.width = dataArea.getWidth
lastDataArea.domainLength = getDomainAxis.getRange.getLength
return
}
lastDataArea.width = dataArea.getWidth
lastDataArea.domainLength = getDomainAxis.getRange.getLength
} else if(lastDataArea.domainLength != getDomainAxis.getRange.getLength)
lastDataArea.domainLength = getDomainAxis.getRange.getLength
if(lastDataArea.height != dataArea.getHeight) {
if(lastDataArea.height != -1.0 &&
lastDataArea.rangeLength != -1.0)
getRangeAxis.setRange(
new org.jfree.data.Range(
getRangeAxis.getLowerBound,
getRangeAxis.getLowerBound + lastDataArea.rangeLength /
lastDataArea.height * dataArea.getHeight), true, true)
lastDataArea.height = dataArea.getHeight
lastDataArea.rangeLength = getRangeAxis.getRange.getLength
} else if(lastDataArea.rangeLength != getRangeAxis.getRange.getLength)
lastDataArea.rangeLength = getRangeAxis.getRange.getLength
super.draw(g2, area, anchor, parentState, info)
}
// Last data.
private object lastDataArea {
var width: Double = -1.0
var height: Double = -1.0
var domainLength: Double = -1.0
var rangeLength: Double = -1.0
}
}
Afterwards, you can simple add this
ExpandableXYPlot to your
XYPlot class like below:
Code: Select all
val plot = new XYPlot(myDataset, xAxis, yAxis, renderer) with ExpandableXYPlot
That's all, now the chart expand itself if you resize it. And for prevent this font stretching, simple override the painComponent Methode for
ChartPanel like below:
Code: Select all
val chartPanel = new ChartPanel {
override override def paintComponent(g: Graphics) {
setMaximumDrawWidth(getWidth)
setMaximumDrawHeight(getHeight)
super.paintComponent(g)
}
}
My solution adjust the axises before it would be drawn and use the last width and height in pixels as reference for calculation.
EDIT: Have modified the code with some default validity checks and support for positive/negative axis values. So, that calculation after zoom in and out have no trouble.
EDIT: Disabled notification after
setRange(_, false, false), this reduce redrawing.