2012-07-03 25 views
15

Yêu cầu- Xây dựng một AreaChart động với dữ liệu truyền trực tuyến thời gian thực. Có thể âm mưu 300 điểm dữ liệu mỗi 1 giây.Cách ánh xạ dữ liệu phát trực tuyến theo thời gian thực bằng AreaChart trong JAVAFX 2 - Đồng thời, Hoạt ảnh, Biểu đồ

Details- Vì vậy, tôi cần phải đọc thời gian thực trực tuyến dữ liệu từ một thiết bị y tế, các mẫu hơi thở của bệnh nhân và hiển thị nó trong một thời trang dạng sóng sử dụng AreaChart trong JavaFX. Tôi mới sử dụng JavaFX và vì vậy tôi đã xây dựng một POC nhỏ, để xem cách hoạt động đồng thời và hoạt ảnh trong JavaFX.

Khái niệm này hoạt động và tôi hài lòng với bài kiểm tra cơ bản, miễn là thực hiện chức năng. Nhưng tôi không hài lòng với hiệu suất tôi nhận được từ mã bên dưới.

Trong mã hoạt động bên dưới, tôi tạo một chuỗi riêng biệt để mô phỏng việc tìm nạp dữ liệu từ thiết bị y tế. Chủ đề chỉ tạo ra một số ngẫu nhiên và thêm nó vào một ConcurrentLinkedQueue.

Chuỗi ứng dụng JavaFX kéo dữ liệu này ra khỏi hàng đợi, thông qua Dòng thời gian và thêm nó vào một chuỗi AreaChart.

Loại này cung cấp cho tôi hoạt ảnh tôi cần và dữ liệu đang được thêm vào trong thời gian chạy. Bạn có thể sao chép và dán mã này và kiểm tra nó .. Nó sẽ hoạt động.

NHƯNG hiệu suất không ấn tượng - CPU sử dụng 56% - Tôi có Intel Core 2 Duo @ 2.53 GHZ và 4GB ram trên máy tính xách tay của mình. Card đồ họa của tôi là Mobile Intel 4 Series thể hiện bằng trình điều khiển mới nhất.

Làm cách nào để cải thiện hoạt ảnh này hoặc vẽ dữ liệu thời gian thực, để có được hiệu suất tốt hơn?

LƯU Ý: Tôi sẵn sàng thỏa hiệp về hoạt ảnh, nếu cổ chai của nó. Tôi đang mở để triển khai như được hiển thị ở đây http://smoothiecharts.org/ nơi dạng sóng chỉ được dựng sẵn và chỉ phát trực tiếp từ phải sang trái.

import java.util.concurrent.ConcurrentLinkedQueue; 
    import java.util.concurrent.ExecutorService; 
    import java.util.concurrent.Executors; 
    import java.util.logging.Level; 
    import java.util.logging.Logger; 
    import javafx.animation.Animation; 
    import javafx.animation.KeyFrame; 
    import javafx.animation.SequentialTransition; 
    import javafx.animation.Timeline; 
    import javafx.application.Application; 
    import javafx.event.ActionEvent; 
    import javafx.event.EventHandler; 
    import javafx.scene.Group; 
    import javafx.scene.Scene; 
    import javafx.scene.chart.AreaChart; 
    import javafx.scene.chart.NumberAxis; 
    import javafx.scene.chart.XYChart.Series; 
    import javafx.stage.Stage; 
    import javafx.util.Duration; 

    /** 
    * A chart that fills in the area between a line of data points and the axes. 
    * Good for comparing accumulated totals over time. 
    * 
    * @see javafx.scene.chart.Chart 
    * @see javafx.scene.chart.Axis 
    * @see javafx.scene.chart.NumberAxis 
    * @related charts/line/LineChart 
    * @related charts/scatter/ScatterChart 
    */ 
    public class AreaChartSample extends Application { 
     private Series series; 
     private int xSeriesData=0; 
     private ConcurrentLinkedQueue<Number> dataQ = new ConcurrentLinkedQueue<Number>(); 
     private ExecutorService executor; 
     private AddToQueue addToQueue; 
     private Timeline timeline2; 
     private SequentialTransition animation; 

     private void init(Stage primaryStage) { 
      Group root = new Group(); 
      primaryStage.setScene(new Scene(root)); 

      NumberAxis xAxis = new NumberAxis(); 
      xAxis.setAutoRanging(true); 

      NumberAxis yAxis = new NumberAxis(); 
      yAxis.setAutoRanging(true); 

      //-- Chart 
      final AreaChart<Number,Number> sc = new AreaChart<Number,Number>(xAxis,yAxis); 
      sc.setId("liveAreaChart"); 
      sc.setTitle("Animated Area Chart"); 

      //-- Chart Series 
      series=new AreaChart.Series<Number,Number>(); 
      series.setName("Area Chart Series"); 
      series.getData().add(new AreaChart.Data<Number, Number>(5d, 5d)); 
      sc.getData().add(series); 


      root.getChildren().add(sc); 



     } 

     @Override public void start(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(String[] args) { launch(args); } 

     private class AddToQueue extends Thread { 

      public void run(){ 

      try { 
       Thread.currentThread().setName(Thread.currentThread().getId()+"-DataAdder"); 
       //-- Add Random numbers to Q 
       dataQ.add(Math.random()); 
       Thread.sleep(50); 

       executor.execute(addToQueue); 

      } catch (InterruptedException ex) { 
       Logger.getLogger(AreaChartSample.class.getName()).log(Level.SEVERE, null, ex); 
      } 

      } 
     } 

     //-- Timeline gets called in the JavaFX Main thread 
     private void prepareTimeline(){ 
      //-- Second slower timeline 
      timeline2 = new Timeline(); 
      //-- This timeline is indefinite. 
      timeline2.setCycleCount(Animation.INDEFINITE); 

      timeline2.getKeyFrames().add(
        new KeyFrame(Duration.millis(100), new EventHandler<ActionEvent>() { 
         @Override public void handle(ActionEvent actionEvent) { 
          addDataToSeries(); 

         } 
        }) 
     ); 

      //-- Set Animation- Timeline is created now. 
      animation = new SequentialTransition(); 
      animation.getChildren().addAll(timeline2); 
      animation.play();   

     } 

     private void addDataToSeries(){ 

      for(int i=0;i<20;i++){ //-- add 20 numbers to the plot 
       if(dataQ.isEmpty()==false) { 
        series.getData().add(new AreaChart.Data(xSeriesData++,dataQ.remove())); 

        //-- Get rid of a bunch from the chart 
        if (series.getData().size() > 1000) { 
         series.getData().remove(0,999); 
        } 

       } 
       else{ 
        return; 
       } 
      } 
     } 


    } 
+0

Câu hỏi này được đăng chéo (và trả lời tốt) trên [chuỗi diễn đàn Java JavaFX] (https://forums.oracle.com/forums/thread.jspa?threadID=2411087). – jewelsea

Trả lời

1

Như jewelsea ghi trong/nhận xét của mình:

Câu hỏi này đã được đăng tải chéo (và trả lời tốt) trên một Oracle JavaFX forum thread.

Để tóm tắt, giải pháp bao gồm trong:

  • Biến hình ảnh động tắt vì nó được thiết kế cho dữ liệu thay đổi chậm hơn để nó được sinh động khi đến nơi;
  • Thay đổi Timeline thành AnimationTimer vì bạn muốn cập nhật biểu đồ mọi khung hình để giữ đồng bộ với dữ liệu đến và di chuyển trơn tru nhất có thể;
  • Sửa luồng khi OP không cần mở rộng Chỉ khi sử dụng Trình kiểm tra. Thay đổi việc tạo dịch vụ thi hành.
0

Sự sụt giảm hiệu suất lớn có thể đến từ việc thu thập dữ liệu của bạn. Không có lý do gì để sử dụng một số ExecutorService và liên tục thêm Threads mới để thực thi nó để có được dữ liệu lặp đi lặp lại bổ sung. Bạn có thể giải quyết cho một chủ đề duy nhất mà đọc/nhận dữ liệu và thêm nó vào hàng đợi và bắt đầu nó bằng cách gọi addToQueue.start().Để nó hoạt động đúng, bạn muốn một vòng lặp chạy liên tục trong luồng với sự chậm trễ ở cuối mỗi lần lặp.

Các vấn đề liên quan