【问题标题】:Dynamic Chart using JFreeChart使用 JFreeChart 的动态图表
【发布时间】:2013-07-08 14:11:00
【问题描述】:

我有一个包含 100,000 个样本的数组,这些样本都是双精度类型的。我想显示或绘制这个数组,以便我得到一个移动的图表/绘图(动态),而不是一次显示它。谁能帮我吗。在情节中 ee[] 和 y[] 是经过一些处理得到的。

private byte[] FileR(String filename) {
    byte[] data = null;
    AudioInputStream ais;
    try {
        File fileIn = new File(filename);
        if (fileIn.exists()) {
            ais = AudioSystem.getAudioInputStream(fileIn);
            data = new byte[ais.available()];
            ais.read(data);
        }
    } catch (UnsupportedAudioFileException | IOException e) {
        System.out.println(e.getMessage());
        throw new RuntimeException("Could not read " + filename);
    }
    return data;
}

private byte[] Capture(double t) throws LineUnavailableException {
    AudioFormat format = new AudioFormat(48000, 16, 2, true, false);
    DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
    line = (TargetDataLine) AudioSystem.getLine(info);
    line.open(format);
    line.open();
    int size = (int) (line.getBufferSize() * t);
    byte[] b = new byte[size];
    line.start();
    line.read(b, 0, size);
    return b;
}

private void plot(double[] ee, double[] y) {
    XYSeries see = new XYSeries("Filtered");
    for (int i = 0; i < ee.length; i++) {
        see.add(i, ee[i]);
    }
    XYSeriesCollection cee = new XYSeriesCollection();
    cee.addSeries(see);
    XYItemRenderer ree = new StandardXYItemRenderer();
    NumberAxis rangeAxisee = new NumberAxis("Filtered");
    XYPlot subplot1 = new XYPlot(cee, null, rangeAxisee, ree);
    subplot1.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
    XYSeries sy = new XYSeries("Noisy");
    for (int i = 0; i < y.length; i++) {
        sy.add(i, y[i]);
    }
    XYSeriesCollection cy = new XYSeriesCollection();
    cy.addSeries(sy);
    XYItemRenderer ry = new StandardXYItemRenderer();
    NumberAxis rangeAxisy = new NumberAxis("Noisy");
    XYPlot subplot2 = new XYPlot(cy, null, rangeAxisy, ry);
    subplot2.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
    CombinedDomainXYPlot plot = new CombinedDomainXYPlot(new NumberAxis("Domain"));
    plot.setGap(10.0);
    plot.add(subplot1);
    plot.add(subplot2);
    plot.setOrientation(PlotOrientation.VERTICAL);
    JFreeChart chart = new JFreeChart("Adaptive Filter", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
    panel = new ChartPanel(chart, true, true, true, false, true);
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(750, 500);
    frame.add(panel, BorderLayout.CENTER);
    frame.setVisible(true);
}

【问题讨论】:

  • 什么意思?你的意思是它在运行时改变?动画?
  • 也许您正在寻找here 所示的方法之一。
  • 奥利弗沃特金斯,可能你有我的问题。你能帮帮我吗?
  • @OliverWatkins 可能看不到您的回复,除非您使用 @ 符号。在此期间,请编辑您的问题以阐明它与 Q&A 有何不同。

标签: java jfreechart


【解决方案1】:

您需要有一个线程来处理所有这些数据。例如从您的后端。然后,每次图表有一组新数据时,您都需要通过 Event Dispatch Thread 更新图表。如果您的图表数据定期出现,这相当容易(即拉),但如果是推送(即数据更随机),可能会变得更棘手。

从绘图方法中删除所有 GUI 创建:

JFreeChart chart = new JFreeChart("Adaptive Filter", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
panel = new ChartPanel(chart, true, true, true, false, true);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(750, 500);
frame.add(panel, BorderLayout.CENTER);
frame.setVisible(true);

这只需要调用一次。 plot 方法会在每次新数据到来时被调用。

这是一个简单的方法:

public void startCharting() {

    final MySoundCard card = new MySoundCard();
    final MyJFreeChart chart = new MyJFreeChart();

    Runnable r = new Runnable() {

        @Override
        public void run() {
            while(true) {

                int[] i = card.FileR();


                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {

                        chart.plot();
                    }

                });


                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    };

    Thread t = new Thread(r);
    t.start();
}

一个线程每秒调用一次您的数据源,然后更新图表。在事件调度线程中调用更新。

【讨论】:

  • 从音频文件接收或从声卡捕获的数据(样本数组)。现在我想以移动方式(动态 - 不是时间序列)显示那个,而不是一次性显示。如果可能,请举例说明。
  • 首先,您的数据是如何进入您的应用程序的。你在调用一个方法吗?还是在您的应用程序中以某种方式捕获了数据?
  • @AbdulBaseerBuriro 我添加了一些代码,应该会给你一个想法。
  • 数据来自方法调用。一种方法是从文件中获取数据,第二种方法是从卡中获取。这取决于用户的选择。
  • @AbdulBaseerBuriro 你应该在你的问题中粘贴一些代码。真的无法为您提供更多帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多