【问题标题】:Recompute JFreeChart display on ChartPanel resize重新计算 ChartPanel 上的 JFreeChart 显示调整大小
【发布时间】:2021-12-11 16:13:43
【问题描述】:

我在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);
}

【问题讨论】:

  • 我是否正确,您希望图表在调整框架大小时平滑调整大小?为什么aspect-ratio?为什么不swing
  • @trashgod 是的。具体来说,当框架较大时,文本显得太宽,而当框架较小时,文本显得太窄,当我想让它的大小独立于框架大小时。因此使用aspect-ratio 标签,因为它不像Swing(布局管理器)问题。我会在我使用计算机时尝试您的解决方案,感谢您抽出宝贵时间。

标签: java resize jfreechart aspect-ratio


【解决方案1】:

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

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

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

首选尺寸:

较小的尺寸:

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 https://stackoverflow.com/q/69720552/230513
 */
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);
    }
}

【讨论】:

  • 感谢您的链接。不幸的是,当帧大小发生变化时,文本仍然显示失真。我相信问题在于 JFreeChart 本身,而不是 Swing 布局管理器。
  • (关于 EDT,当第一个 setVisible(true) 被调用时,它是 spawned,所以对于 SSCCE 来说这不是什么大问题,但与 Swing 相关的东西确实应该在那里处理,否则(不那么)有趣的事情会发生)
  • 在框架的大小低于图表面板的最小绘制宽度和高度之前,我无法重现这一点。框架和图表面板之间有布局吗?还要检查版本;在 v1.0.13+ 中,useBuffer 默认值已更改。
  • 有趣...我使用的是 1.0.16,刚刚在 freshly compiled 1.5.3 上进行了测试,但结果相同,在 Ubuntu Linux 上使用 Java 14.0.2。我想我必须检查 Windows VM 以查看是否得到相同的结果:当框架具有较大的宽度和较短的高度时,会更好地看到问题。明天晚上我会再做一些测试,如果我发现任何东西,我会用更多的细节更新我的问题......
  • 很高兴你把它整理好了,感谢你花时间解决这个问题;通常,我依靠默认行为来显示缩略图。顺便说一句,我习惯性地覆盖getPreferredSize,因为默认值可能会在上游发生变化。
猜你喜欢
  • 1970-01-01
  • 2012-09-28
  • 1970-01-01
  • 1970-01-01
  • 2013-02-15
  • 1970-01-01
  • 2012-12-22
  • 1970-01-01
  • 2012-01-24
相关资源
最近更新 更多