如何在java中使用JFreechart绘制移动和运行正弦波形图?

时间:2014-03-13 07:24:42

标签: java swing animation awt jfreechart

我使用JFreeChart在java中使用netbeans绘制Running或Moving Sine Wave。我为它编写代码,但它不喜欢移动或运行正弦波图。所以,如果您对此有任何想法,那么建议我。 我的代码在

之下
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;


public class DrawChart extends ApplicationFrame implements ActionListener {

    public XYSeries series;

    public DrawChart(final String title) {

        super(title);
        series = new XYSeries("Sine", true, true);
        XYSeriesCollection dataset = new XYSeriesCollection(series);
        final JFreeChart chart = createChart(dataset);

        final ChartPanel chartPanel = new ChartPanel(chart);
        final JButton button = new JButton("Add New Data Item");
        button.setActionCommand("ADD_DATA");
        button.addActionListener(this);

        final JPanel content = new JPanel(new BorderLayout());
        content.add(chartPanel);
        content.add(button, BorderLayout.SOUTH);
        chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
        setContentPane(content);

    }

    private JFreeChart createChart(final XYDataset dataset) {
        JFreeChart jfreechart = ChartFactory.createXYLineChart("Sin Curve", "Angle (Deg)", "Value", dataset, PlotOrientation.VERTICAL, true, true, true);
        jfreechart.setBackgroundPaint(Color.white);
        XYPlot xyplot = (XYPlot) jfreechart.getPlot();
        xyplot.setBackgroundPaint(Color.lightGray);
        xyplot.setDomainGridlinePaint(Color.white);
        xyplot.setRangeGridlinePaint(Color.white);
        return jfreechart;
    }

    public void actionPerformed(final ActionEvent e) {
        if (e.getActionCommand().equals("ADD_DATA")) {
            for (int i = 0; i < 100; i++) {
                final double x = (i)/10.0 ;
                final double y = Math.sin(x);
                this.series.addOrUpdate(x, y);
            }
        }
    }

    public static void main(final String[] args) {

        final DrawChart demo = new DrawChart("Dynamic Data view");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }
}

3 个答案:

答案 0 :(得分:5)

从这个example开始,用Math.sin()代替nextGaussian()产生了下面的插图。 javax.swing.Timer以1 Hz的速度调整动画。

image

private ChartPanel createPane() {
    final XYSeries series = new XYSeries("Data");
    for (int i = 0; i < random.nextInt(N) + N / 2; i++) {
        series.add(i, Math.sin(i));
    }
    XYSeriesCollection dataset = new XYSeriesCollection(series);
    new Timer(1000, new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            series.add(series.getItemCount(), Math.sin(series.getItemCount()));
        }
    }).start();
    …
}

答案 1 :(得分:4)

试试这个JavaFX。它更强灵活

答案 2 :(得分:1)

这是我收集并使用JavaFX

提出的
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javafx.animation.AnimationTimer;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart.Series;
import javafx.stage.Stage;

public class ACS extends Application
{
    private static final int MAX_DATA_POINTS = 200;

    private Series series;
    private float xSeriesData = 0;
    private final ConcurrentLinkedQueue<Number> dataQ = new ConcurrentLinkedQueue<Number>();
    private ExecutorService executor;
    private AddToQueue addToQueue;
    private Timeline timeline2;
    private NumberAxis xAxis;

    private void init(final Stage primaryStage)
    {
        xAxis = new NumberAxis(0, MAX_DATA_POINTS, 1);
        xAxis.setForceZeroInRange(false);
        xAxis.setAutoRanging(false);

        final NumberAxis yAxis = new NumberAxis(0, 200, 1);
        yAxis.setAutoRanging(false);

        // -- Chart
        final LineChart<Number, Number> sc = new LineChart<Number, Number>(xAxis, yAxis) {
            // Override to remove symbols on each data point
            @Override
            protected void dataItemAdded(final Series<Number, Number> series, final int itemIndex, final Data<Number, Number> item)
            {}
        };
        sc.setAnimated(false);
        sc.setId("liveAreaChart");
        sc.setTitle("Animated Area Chart");
        // -- Chart Series
        series = new LineChart.Series<Number, Number>();
        series.setName("Area Chart Series");
        sc.getData().add(series);

        final Scene scene = new Scene(sc, 800, 800);
        scene.getStylesheets().add("site.css");
        sc.getStyleClass().add("thick-chart");

        primaryStage.setScene(scene);
    }

    @Override
    public void start(final Stage primaryStage) throws Exception
    {
        init(primaryStage);
        primaryStage.show();

        // -- Prepare Executor Services
        executor = Executors.newCachedThreadPool();
        addToQueue = new AddToQueue();
        executor.execute(addToQueue);
        // -- Prepare Timeline
        prepareTimeline();
    }

    public static void main(final String[] args)
    {
        launch(args);
    }

    private class AddToQueue implements Runnable
    {
        double PERIOD = 20;
        double SCALE = 20;
        int pos = 0;

        @Override
        public void run()
        {
            try {
                final double Min = 20;
                final double Max = 55;
                // add a item of random data to queue
//uncomment the line below to generate a normal graph
                // dataQ.add(Min + (Math.random() * ((Max - Min))));
                dataQ.add(((Math.sin((++pos * 2 * Math.PI) / PERIOD) * (SCALE / 2)) + (SCALE / 2)));
                Thread.sleep(1000);
                executor.execute(this);
            }
            catch (final InterruptedException ex) {
                // Logger.getLogger(ACS.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    // -- Timeline gets called in the JavaFX Main thread
    private void prepareTimeline()
    {
        // Every frame to take any data from queue and add to chart
        new AnimationTimer() {
            @Override
            public void handle(final long now)
            {
                addDataToSeries();
            }
        }.start();
    }

    private void addDataToSeries()
    {
        for (int i = 0; i < 20; i++) { // -- add 20 numbers to the plot+
            if (dataQ.isEmpty()) {
                break;
            }
            // series.getData().add(new LineChart.Data(xSeriesData++, dataQ.remove()));

            final Number datapoint = dataQ.remove();
            xSeriesData = xSeriesData + 1;
            System.out.println(xSeriesData + "  " + datapoint);
            series.getData().add(new LineChart.Data(xSeriesData, datapoint));
        }
        // remove points to keep us at no more than MAX_DATA_POINTS
        if (series.getData().size() > (MAX_DATA_POINTS * 10)) {
            series.getData().remove(0, series.getData().size() - (MAX_DATA_POINTS * 10));
        }
        // update
        xAxis.setLowerBound(xSeriesData - (MAX_DATA_POINTS));
        xAxis.setUpperBound(xSeriesData - 1);
    }
}