在调整 ChartPanel 大小时重新计算 JFreeChart 显示

Recompute JFreeChart display on ChartPanel resize

我在 ChartPanel 中嵌入了一张图表。首次渲染面板时,一切看起来都不错:

但是当尺寸改变时,面板内容被拉伸,使文本更难阅读:

这就像 JFreeChart 正在预渲染显示,因此它可以快速在屏幕上绘制它,这对于例如PNG 导出(我知道这是 JFreeChart 作者 David Gilbert 想要保留的一个功能),但是当购物车尺寸变化太大时,显示效果不佳。

有没有办法告诉 JFreeChart 在容器调整大小时以某种方式重新呈现图表?

这是 SSCCE:

public static void main(String[] args) {
    JFrame frm = new JFrame("JFreeChart resizing");
    frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    CategoryDataset ds = new DefaultCategoryDataset();
    JFreeChart chart = ChartFactory.createLineChart("Title", "X axis", "Y axis", ds);
    ChartPanel cp = new ChartPanel(chart);
    frm.getContentPane().add(cp, BorderLayout.CENTER);
    
    frm.pack();
    frm.setVisible(true);
}

Solving Common Layout Problems 建议,“确保您的组件的容器使用尊重组件请求大小的布局管理器。”您的片段使用 BorderLayout.CENTER,这是一个不错的选择:它允许 ChartPanel 在调整框架大小时平滑地调整大小,但它会忽略面板的最小尺寸。最终,出现重采样伪像和失真。当您想保留调整大小行为时,一种方法是将图表面板的最小绘制宽度和高度设置为零,并(可选)相应地限制框架的最小尺寸:

cp.setMinimumDrawWidth(0);
cp.setMinimumDrawHeight(0);
// optionally
f.setMinimumSize(new Dimension(
    cp.getMinimumDrawWidth(),
    cp.getMinimumDrawHeight()));

绘图宽度和高度也可以在构造函数中指定,如 here 所示。在下面的例子中,注意:

  • 覆盖 getPreferredSize() to establish the initial preferred size, also discussed here

  • event dispatch thread.

    构造和操作 Swing GUI 对象

首选尺码:

较小的尺寸:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;

/**
 * @see 
 */
public class ChartTest {

    private static final int W = 320;
    private static final int H = 240;

    private void display() {
        JFrame f = new JFrame("JFreeChart Resizing");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        CategoryDataset ds = new DefaultCategoryDataset();
        JFreeChart chart = ChartFactory.createLineChart(
            "Chart Title", "X axis", "Y axis", ds);
        ChartPanel cp = new ChartPanel(chart) {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(W, H);
            }
        };
        f.add(cp, BorderLayout.CENTER);
        f.add(new JLabel("Java v" + System.getProperty("java.version")
            + "; JFreeChart 1.5.3", JLabel.CENTER), BorderLayout.PAGE_END);
        cp.setMinimumDrawWidth(0);
        cp.setMinimumDrawHeight(0);
        f.setMinimumSize(new Dimension(cp.getMinimumDrawWidth(), cp.getMinimumDrawHeight()));
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new ChartTest()::display);
    }
}