3

我目前正在开发一个程序,其中某些数值变量会随着时间的推移而变化,它们的值会在每次迭代中显示出来。这很好用,但现在我想绘制一个图表,显示它们随时间的演变。因此,我研究了一个在 Swing 中绘制图形的代码示例。我的最终代码如下所示:

public class Populus3 extends JPanel
{
    public static void main(String[] args) throws IOException {

        final Populus3 pop = new Populus3();

        JFrame f = new JFrame(); //where I want to plot the graph
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new GraphingData());
        f.setSize(400,400);
        f.setLocation(200,200);
        f.setVisible(true);


        frame = new JFrame("Animation Frame"); //where I'm running animation for another element of the program
        frame.add(pop, BorderLayout.CENTER);
        frame.setSize(graphSize, graphSize);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //insert all sort of things

    }


    public void paint(Graphics g) 
    {
        super.paint(g);
        paintCell(g, 1);
        Toolkit.getDefaultToolkit().sync(); // necessary for linux users to draw  and animate image correctly
        g.dispose();
    }


      public void actionPerformed(ActionEvent e) {
        repaint();
    }



    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        for(int i = 0; i < particleType.length; i++)
            paintCell(g, i);  //a method that draws a small circle for the animation panel
    }



    public static class GraphingData extends JPanel {
        int[] data = {
            21, 14, 18, 03, 86, 88, 74, 87, 54, 77,
            61, 55, 48, 60, 49, 36, 38, 27, 20, 18
        };
        final int PAD = 20;

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D)g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                RenderingHints.VALUE_ANTIALIAS_ON);
            int w = getWidth();
            int h = getHeight();
            // Draw ordinate.
            g2.draw(new Line2D.Double(PAD, PAD, PAD, h-PAD));

            // Draw abcissa.
            g2.draw(new Line2D.Double(PAD, h-PAD, w-PAD, h-PAD));
            double xInc = (double)(w - 2*PAD)/(data.length-1);
            double scale = (double)(h - 2*PAD)/getMax();
            // Mark data points.
            g2.setPaint(Color.red);
            for(int i = 0; i < data.length; i++) {
                double x = PAD + i*xInc;
                double y = h - PAD - scale*data[i];
                g2.fill(new Ellipse2D.Double(x-2, y-2, 4, 4));
            }
        }

        private int getMax() {
            int max = -Integer.MAX_VALUE;
            for(int i = 0; i < data.length; i++) {
                if(data[i] > max)
                    max = data[i];
            }
            return max;
        }
    }
}

现在,动画面板工作得很好。另一方面,图形面板......当我运行程序时,它显示一堆红点,没有线连接它们。我究竟做错了什么?

4

3 回答 3

6

除了@Hovercraft 的有用建议外,还可以考虑以下其他方法:

  • 累积 a 中的点GeneralPath,可以根据需要渲染,例如

利萨茹图片

  • 使用重复调用连接点以drawLine()使用合适的坐标系,此处概述。

正弦图像

于 2013-07-08T23:54:54.863 回答
5

你的代码让我很困惑:

  • 您为 Populus3 JPanel 覆盖了paint 和paintComponent——为什么?您应该只覆盖paintComponent,除非您绝对必须让您的绘图影响组件的子项和边框。
  • 您处理传递给绘画的 Graphics 对象——这是一件非常危险的事情。您永远不应该处理 JVM 提供给您的 Graphics 对象,只能处理您自己创建的 Graphics 对象。
  • 您反复调用此处未为我们定义的方法,paintCell(...).
  • 我从未听说过需要Toolkit.getDefaultToolkit().sync();Swing 应用程序。你有这个需求的参考吗?
  • 您提到“动画”,但我没有看到动画代码。
  • 在您的 GraphingData 类的 paintComponent 方法中,您在 for 循环中填充椭圆,但您永远不会将它们与线条连接起来,因此您在图表中只看到点而没有线条也就不足为奇了。

考虑更多地隔离您的问题并发布sscce,这是一个我们可以编译、运行、修改和更正的最小测试程序,它向我们展示了您的问题,但没有与问题无关或演示所需的额外代码。

于 2013-07-08T21:33:16.887 回答
2

下面的代码演示了一个使用XChart的实时 Java 图表,其中线条随着数据随时间的变化而更新。创建实时图表就像updateXYSeries通过实例调用一个或多个系列对象XYChart并触发JPanel包含图表的重绘一样简单。这适用于所有图表类型,包括、XYChart和,可以在此处找到示例源代码:https ://github.com/timmolter/XChart/tree/develop/xchart-demo/src/main/java/org/knowm /xchart/demo/charts/realtime。示例演示了如何使用with方法以及with和。免责声明,我是 XChart 库的主要开发人员。CategoryChartBubbleChartPieChartSwingWrapperrepaintChart()XChartPanelrevalidate()repaint()

public class SimpleRealTime {

  public static void main(String[] args) throws Exception {

    double phase = 0;
    double[][] initdata = getSineData(phase);

    // Create Chart
    final XYChart chart = QuickChart.getChart("Simple XChart Real-time Demo", "Radians", "Sine", "sine", initdata[0], initdata[1]);

    // Show it
    final SwingWrapper<XYChart> sw = new SwingWrapper<XYChart>(chart);
    sw.displayChart();

    while (true) {

      phase += 2 * Math.PI * 2 / 20.0;

      Thread.sleep(100);

      final double[][] data = getSineData(phase);

      chart.updateXYSeries("sine", data[0], data[1], null);
      sw.repaintChart();

    }

  }

  private static double[][] getSineData(double phase) {

    double[] xData = new double[100];
    double[] yData = new double[100];
    for (int i = 0; i < xData.length; i++) {
      double radians = phase + (2 * Math.PI / xData.length * i);
      xData[i] = radians;
      yData[i] = Math.sin(radians);
    }
    return new double[][] { xData, yData };
  }
}

这将产生以下 Java Swing 实时图表应用程序: 在此处输入图像描述

于 2016-07-27T09:24:10.297 回答