【问题标题】:Drawing a graph that updates in realtime based on input using Java?使用 Java 绘制基于输入实时更新的图形?
【发布时间】:2012-10-02 16:52:12
【问题描述】:

所以我对在 java 中进行图形绘图的经验很少,所以我的第一个问题本质上是:为了在 java 中绘制图形,我应该查看哪些教程?

第二个问题是我的主要任务。我希望能够使用从文件中获取的新数据实时(或每 10 秒)更新 java 中的图形,即:我将通过管道将文件传输到程序,并且每隔一段时间它会检查文件新数据,并用新数据更新可视图形,但这必须是实时的,这意味着图形保留所有先前已绘制的数据,并且可以看到从左到右移动(到达屏幕边缘时然后 X 轴将开始以较大的数字向左移动。

是否有任何已经编写好的算法可以做到这一点?或者如果我必须自己完成这项工作,谁能给我一个关于从哪里开始的指针?

谢谢,

欧登

【问题讨论】:

    标签: java graphics graph


    【解决方案1】:

    为什么不使用 JFreeChart ?它是一个广泛使用的图表库。它声称不适合实时使用,但对于您所说的频率(每 10 秒),它应该非常适合。

    This answer 链接到一些示例代码。

    【讨论】:

    • JFreeChart 非常适合我的需求。谢谢!
    【解决方案2】:

    如果您可以使用 Java 7,请查看 JavaFX API。 Oracle 的 Ensemble 示例附带了一个股票代码(图表 -> 线条 -> 高级股票)。这是您想要实现的目标的良好开端。下面是Oracle提供的代码:

    import javafx.application.Application;
    import javafx.scene.Group;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    import javafx.animation.Animation;
    import javafx.animation.KeyFrame;
    import javafx.animation.Timeline;
    import javafx.event.ActionEvent;
    import javafx.event.EventHandler;
    import javafx.scene.chart.LineChart;
    import javafx.scene.chart.NumberAxis;
    import javafx.scene.chart.XYChart;
    import javafx.util.Duration;
    
    /**
     * A simulated stock line chart.
     *
     * @see javafx.scene.chart.Chart
     * @see javafx.scene.chart.LineChart
     * @see javafx.scene.chart.NumberAxis
     * @see javafx.scene.chart.XYChart
     */
    public class AdvancedStockLineChartSample extends Application {
    
        private XYChart.Series<Number,Number> hourDataSeries;
        private XYChart.Series<Number,Number> minuteDataSeries;
        private NumberAxis xAxis;
        private Timeline animation;
    
        private double hours = 0;
        private double minutes = 0;
        private double timeInHours = 0;
        private double prevY = 10;
        private double y = 10;
    
        private void init(Stage primaryStage) {
            Group root = new Group();
            primaryStage.setScene(new Scene(root));
            root.getChildren().add(createChart());
            // create timeline to add new data every 60th of second
            animation = new Timeline();
            animation.getKeyFrames().add(new KeyFrame(Duration.millis(1000/60), new EventHandler<ActionEvent>() {
                @Override public void handle(ActionEvent actionEvent) {
                    // 6 minutes data per frame
                    for(int count=0; count < 6; count++) {
                        nextTime();
                        plotTime();
                    }
                }
            }));
            animation.setCycleCount(Animation.INDEFINITE);
        }
    
        protected LineChart<Number, Number> createChart() {
            xAxis = new NumberAxis(0,24,3);
            final NumberAxis yAxis = new NumberAxis(0,100,10);
            final LineChart<Number,Number> lc = new LineChart<Number,Number>(xAxis,yAxis);
            // setup chart
            lc.setId("lineStockDemo");
            lc.setCreateSymbols(false);
            lc.setAnimated(false);
            lc.setLegendVisible(false);
            lc.setTitle("ACME Company Stock");
            xAxis.setLabel("Time");
            xAxis.setForceZeroInRange(false);
            yAxis.setLabel("Share Price");
            yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis,"$",null));
            // add starting data
            hourDataSeries = new XYChart.Series<Number,Number>();
            hourDataSeries.setName("Hourly Data");
            minuteDataSeries = new XYChart.Series<Number,Number>();
            minuteDataSeries.setName("Minute Data");
            // create some starting data
            hourDataSeries.getData().add(new XYChart.Data<Number,Number>(timeInHours,prevY));
            minuteDataSeries.getData().add(new XYChart.Data<Number,Number>(timeInHours,prevY));
            for (double m=0; m<(60); m++) {
                nextTime();
                plotTime();
            }
            lc.getData().add(minuteDataSeries);
            lc.getData().add(hourDataSeries);
            return lc;
        }
    
        private void nextTime() {
            if (minutes == 59) {
                hours ++;
                minutes = 0;
            } else {
                minutes ++;
            }
            timeInHours = hours + ((1d/60d)*minutes);
        }
    
        private void plotTime() {
            if ((timeInHours % 1) == 0) {
                // change of hour
                double oldY = y;
                y = prevY - 10 + (Math.random()*20);
                prevY = oldY;
                while (y < 10 || y > 90) y = y - 10 + (Math.random()*20);
                hourDataSeries.getData().add(new XYChart.Data<Number, Number>(timeInHours, prevY));
                // after 25hours delete old data
                if (timeInHours > 25) hourDataSeries.getData().remove(0);
                // every hour after 24 move range 1 hour
                if (timeInHours > 24) {
                    xAxis.setLowerBound(xAxis.getLowerBound()+1);
                    xAxis.setUpperBound(xAxis.getUpperBound()+1);
                }
            }
            double min = (timeInHours % 1);
            double randomPickVariance = Math.random();
            if (randomPickVariance < 0.3) {
                double minY = prevY + ((y-prevY) * min) - 4 + (Math.random()*8);
                minuteDataSeries.getData().add(new XYChart.Data<Number,Number>(timeInHours,minY));
            } else if (randomPickVariance < 0.7) {
                double minY = prevY + ((y-prevY) * min) - 6 + (Math.random()*12);
                minuteDataSeries.getData().add(new XYChart.Data<Number,Number>(timeInHours,minY));
            } else if (randomPickVariance < 0.95) {
                double minY = prevY + ((y-prevY) * min) - 10 + (Math.random()*20);
                minuteDataSeries.getData().add(new XYChart.Data<Number,Number>(timeInHours,minY));
            } else {
                double minY = prevY + ((y-prevY) * min) - 15 + (Math.random()*30);
                minuteDataSeries.getData().add(new XYChart.Data<Number,Number>(timeInHours,minY));
            }
            // after 25hours delete old data
            if (timeInHours > 25) minuteDataSeries.getData().remove(0);
        }
    
       public void play() {
            animation.play();
        }
    
        @Override public void stop() {
            animation.pause();
        }    
    
        @Override public void start(Stage primaryStage) throws Exception {
            init(primaryStage);
            primaryStage.show();
            play();
        }
        public static void main(String[] args) { launch(args); }
    }
    

    屏幕截图:

    【讨论】:

    • 我不知道 JavaFX。虽然我使用了 JFreeChart,但这很有用。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-09
    相关资源
    最近更新 更多