Reputation: 11873
I'm using jFreeChart to display this kind of plot:
Well, the problem is that when the program runs on a monitor with >800px height the dark shadows and the 45 dashed line are not painted correctly.
I've found that the problem is caused by a wrong value returned by:
chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(0).getDataArea()
The dataArea is not correct, the height is wrong, and thus the shadows are not painted where expected. But this only happens when resizing the window above ~800px height.
I've managed to reproduce the error with a small SSCCE (jcommon and jfreechart needed):
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CombinedDomainXYPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.RectangleInsets;
public class Window extends JFrame implements ComponentListener {
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private XYPlot subplotTop;
private XYPlot subplotBottom;
private CombinedDomainXYPlot plot;
private JFreeChart chart;
private ChartPanel chartPanel;
private JLabel label;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Window frame = new Window();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Window() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 700, 500);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JPanel example = new JPanel();
label = new JLabel("Resize this window (do not use the \"maximize\" button");
example.add( label );
contentPane.add( example, BorderLayout.NORTH );
createTopChart();
createBottomChart();
createCombinedChart();
chartPanel = new ChartPanel(chart);
this.add(chartPanel, BorderLayout.CENTER);
//window resize listener
this.addComponentListener(this);
}
private void createTopChart() {
subplotTop = new XYPlot();
subplotTop.setDomainPannable(true);
subplotTop.setBackgroundPaint(Color.lightGray);
subplotTop.setDomainGridlinePaint(Color.white);
subplotTop.setRangeGridlinePaint(Color.white);
XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false);
subplotTop.setRenderer(renderer);
NumberAxis range = new NumberAxis("dBA");
range.setRange(30, 120);
range.setAutoRange(false);
subplotTop.setRangeAxis(range);
TimeSeriesCollection dataset_L = randomDataset(30,120);
subplotTop.setDataset(dataset_L);
}
private void createBottomChart(){
subplotBottom = new XYPlot();
subplotBottom.setDomainPannable(true);
subplotBottom.setBackgroundPaint(Color.lightGray);
subplotBottom.setDomainGridlinePaint(Color.white);
subplotBottom.setRangeGridlinePaint(Color.white);
XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false);
subplotBottom.setRenderer(renderer);
NumberAxis range = new NumberAxis("%");
range.setRange(-10, 100);
range.setAutoRange(false);
subplotBottom.setRangeAxis(range);
TimeSeriesCollection dataset_P = randomDataset(0,100);
subplotBottom.setDataset(dataset_P);
}
private void createCombinedChart() {
plot = new CombinedDomainXYPlot();
plot.setGap(30);
plot.add(subplotTop, 4);
plot.add(subplotBottom, 1);
plot.setOrientation(PlotOrientation.VERTICAL);
chart = new JFreeChart("Title", new Font("Arial", Font.BOLD, 18), plot, true);
chart.getLegend().setVisible(false);
chart.getLegend().setPosition(RectangleEdge.RIGHT);
chart.getTitle().setMargin(new RectangleInsets(15,5,15,5));
chart.getTitle().setPaint(Color.BLACK);
}
private TimeSeriesCollection randomDataset(float min, float max) {
return null;
}
private void showAreas() {
Rectangle2D screenDataAreaChartPanel = this.chartPanel.getScreenDataArea();
System.out.println("screenDataAreaChartPanel: "+screenDataAreaChartPanel);
Rectangle2D plotArea = this.chartPanel.getChartRenderingInfo().getPlotInfo().getPlotArea();
System.out.println("getPlotArea: "+plotArea.toString());
Rectangle2D dataAreaPlot = this.chartPanel.getChartRenderingInfo().getPlotInfo().getDataArea();
System.out.println("getDataArea: "+dataAreaPlot.toString());
Rectangle2D dataAreaSubplotTop = this.chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(0).getDataArea();
Rectangle2D dataAreaSubplotBottom = this.chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(1).getDataArea();
System.out.println("dataAreaSubplotTop: "+dataAreaSubplotTop.toString());
System.out.println("dataAreaSubplotBottom: "+dataAreaSubplotBottom.toString());
System.out.println();
label.setText("ScreenDataArea.height="+Math.round(screenDataAreaChartPanel.getHeight())+
". SubPlotTop.heigth="+Math.round(dataAreaSubplotTop.getHeight())+
". SubPlotBottom.heigth="+Math.round(dataAreaSubplotBottom.getHeight()));
repaint();
}
@Override
public void componentHidden(ComponentEvent e) {}
@Override
public void componentMoved(ComponentEvent e) { }
@Override
public void componentResized(ComponentEvent e) {
chartPanel.repaint();
chartPanel.revalidate();
this.repaint();
showAreas();
}
@Override
public void componentShown(ComponentEvent e) { }
}
I've used jfreechart v1.0.14 and jcommon v1.0.18.
In the example there are three values above the chart. You will see that the three values grow while you make the window bigger, but at about 800px height, the first value will keep growing while the others don't. Why?
If you don't have a big screen resolution you probably won't see the error, as it happened to me.
Am I doing something wrong? Is that a bug?
Upvotes: 1
Views: 1823
Reputation: 13
I myself had a similar issue.
The issue seems to stem from the chart panel limiting its default maximum size causing the subplot data area to stop updating correctly.
Increasing the max height/width should solve your issue.
panel.setMaximumHeight(2000);
panel.setMaximumSize(1500);
See this bug post for more information. http://sourceforge.net/p/jfreechart/bugs/911/
Upvotes: 1
Reputation: 205785
A few notes:
You may be looking for one of the org.jfree.chart.annotations
, in which "coordinates are specified in data space;" a few examples are seen here.
A JFreeChart
is not a component; a ChartPanel
is a component that repaint's the panel in response to assorted chart events; a ComponentListener
is rarely warranted.
Don't use setBounds()
; instead, pack()
the enclosing Window
; override getPreferredSize()
in the ChartPanel
if the default is unsatisfactory.
Do construct and manipulate Swing GUI objects only on the event dispatch thread.
Upvotes: 1