Chart scaled - can this be turned off

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
liferiot
Posts: 6
Joined: Thu Feb 18, 2010 1:44 pm
antibot: No, of course not.

Chart scaled - can this be turned off

Post by liferiot » Wed Jun 15, 2011 3:32 pm

if i'm adding a chart to the layout allowing it to strech when resizing the window this will cause the labels of the axis to get stretched/scaled.
having the text in a fiexed font would be nice - if the font has to be scaled smaller or bigger this would be ok - but please do not scale my labels only in x-direction for example (widescreen)
also shapes in the chart are scaled... quadratic shapes stretch to rectangles.
can this also or altogether be turned off somehow?

zooming/stretching the chart should only result in longer lines/more ticks etc. - as the chart does by resizing x any y way.

in short: the chart behaves like a scaled image if x/y ratio (what ratio?) is changed.

Image

pfxo
Posts: 7
Joined: Thu Sep 22, 2011 3:15 am
antibot: No, of course not.

Re: Chart scaled - can this be turned off

Post by pfxo » Thu Sep 22, 2011 3:22 am

I would like to know the same. I have a DefaultXYZDataset, XYBlockRenderer and XYPlot to draw my box chart. I wished, if the frame is resized the chart don't stretching itself but rather expand his axis. Like the chart tools for financial products, where the time axis expand if you resize the frame width. How is that realizable?

paradoxoff
Posts: 1634
Joined: Sat Feb 17, 2007 1:51 pm

Re: Chart scaled - can this be turned off

Post by paradoxoff » Thu Sep 22, 2011 5:58 pm

@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.

pfxo
Posts: 7
Joined: Thu Sep 22, 2011 3:15 am
antibot: No, of course not.

Re: Chart scaled - can this be turned off

Post by pfxo » Thu Sep 22, 2011 7:45 pm

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.

Locked