2015-04-07 77 views
1

我從stackoverflow獲取以下代碼,當應用程序開始運行時,動態區域圖正在更新,幾秒鐘後應用程序掛起(即最小化,最大化,關閉窗口按鈕後不工作窗口大小)。但面積圖正在更新。實時區域圖應用程序

package areachartsample; 
import java.util.concurrent.ConcurrentLinkedQueue; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ThreadFactory; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javafx.animation.AnimationTimer; 
import javafx.animation.Timeline; 
import javafx.application.Application; 
import javafx.scene.Scene; 
import javafx.scene.chart.AreaChart; 
import javafx.scene.chart.NumberAxis; 
import javafx.scene.chart.XYChart.Data; 
import javafx.scene.chart.XYChart.Series; 
import javafx.stage.Stage; 


public class AreaChartSample extends Application { 
private static final int MAX_DATA_POINTS = 50; 

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

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

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

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

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

    primaryStage.setScene(new Scene(sc)); 
} 

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

    //-- Prepare Executor Services 
    executor = Executors.newCachedThreadPool(new ThreadFactory() { 
     @Override public Thread newThread(Runnable r) { 
      Thread thread = new Thread(r); 
      thread.setDaemon(true); 
      return thread; 
     } 
    }); 
    addToQueue = new AddToQueue(); 
    executor.execute(addToQueue); 
    //-- Prepare Timeline 
    prepareTimeline(); 
} 

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

private class AddToQueue implements Runnable { 
    public void run() { 
     try { 
      // add a item of random data to queue 
      dataQ.add(Math.random()); 
      Thread.sleep(50); 
      executor.execute(this); 
     } catch (InterruptedException ex) { 
      Logger.getLogger(AreaChartSample.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(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 AreaChart.Data(xSeriesData++, dataQ.remove())); 
    } 
    // remove points to keep us at no more than MAX_DATA_POINTS 
    if (series.getData().size() > MAX_DATA_POINTS) { 
     series.getData().remove(0, series.getData().size() - MAX_DATA_POINTS); 
    } 
    // update 
    xAxis.setLowerBound(xSeriesData-MAX_DATA_POINTS); 
    xAxis.setUpperBound(xSeriesData-1); 
} 
} 
+0

開始取件,直到你有一個最小的應用程序,然後找出(通過試驗和消除)哪個片斷。 – cphlewis

+0

使用執行器服務類,Thread,ConcurrentLinkedQueue,如果我加載按鈕上的區域圖表單擊它正在工作正常 – pavankumar

+1

一次添加它們*一個*直到您確定哪裏出了問題。此外,這段代碼是從stackoverflow? – cphlewis

回答

0

我爲你創建了一個例子。它使用TimeLine進行圖表更新。

import java.util.List; 
import java.util.Random; 

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.Parent; 
import javafx.scene.Scene; 
import javafx.scene.chart.AreaChart; 
import javafx.scene.chart.NumberAxis; 
import javafx.scene.chart.XYChart; 
import javafx.scene.chart.XYChart.Data; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

public class LiveAreaChartApp extends Application { 

    private static int MAX_DATA_POINTS = 10; 
    private static int Y_DATA_RANGE = 100; 
    private static int TICK_UNIT = 10; 

    private static int UPDATE_INTERVAL_MS = 100; 

    private AreaChart.Series<Number, Number> series1; 
    private AreaChart.Series<Number, Number> series2; 
    private AreaChart<Number, Number> areaChart; 
    private NumberAxis xAxis = new NumberAxis(); 
    private NumberAxis yAxis = new NumberAxis(); 

    private SequentialTransition animation; 

    private double nextX = 0; 

    Random rnd = new Random(); 

    public LiveAreaChartApp() { 

     Timeline timeline = new Timeline(); 
     timeline.getKeyFrames().add(new KeyFrame(Duration.millis(UPDATE_INTERVAL_MS), new EventHandler<ActionEvent>() { 
      @Override 
      public void handle(ActionEvent actionEvent) { 

       // update chart data 
       // note that we add one data point and remove one data point in this simple example. 
       // in a production environment you'd have to add multiple and remove multiple data points 

       // add new points 
       series1.getData().add(new XYChart.Data<Number, Number>(nextX, Math.sin(Math.toRadians(nextX)) * Y_DATA_RANGE)); 
       series2.getData().add(new XYChart.Data<Number, Number>(nextX, Math.cos(Math.toRadians(nextX)) * Y_DATA_RANGE)); 

       // remove points that shouldn't be visible anymore 
       if (series1.getData().size() > MAX_DATA_POINTS) { 
        series1.getData().remove(0); 
       } 
       if (series2.getData().size() > MAX_DATA_POINTS) { 
        series2.getData().remove(0); 
       } 

       nextX += 10; 

       // update using series 1 as reference 
       // series 2 contains same amount of data; if it doesn't for your case, 
       // you need to adapt this here and calculate the proper range 
       List<Data<Number, Number>> data = series1.getData(); 
       xAxis.setLowerBound(data.get(0).getXValue().doubleValue()); 
       xAxis.setUpperBound(data.get(data.size() - 1).getXValue().doubleValue()); 

      } 
     })); 
     timeline.setCycleCount(Animation.INDEFINITE); 

     animation = new SequentialTransition(); 
     animation.getChildren().addAll(timeline); 
    } 

    public Parent createContent() { 
     xAxis = new NumberAxis(); 
     xAxis.setForceZeroInRange(false); 
     xAxis.setAutoRanging(false); 
     xAxis.setTickLabelsVisible(false); 
     xAxis.setTickMarkVisible(false); 
     xAxis.setMinorTickVisible(false); 

     yAxis = new NumberAxis(-Y_DATA_RANGE, Y_DATA_RANGE, TICK_UNIT); 
     yAxis.setAutoRanging(false); 

     areaChart = new AreaChart<>(xAxis, yAxis); 
     areaChart.setAnimated(false); 
     areaChart.setLegendVisible(false); 

     series1 = new AreaChart.Series<>(); 
     series1.getData().add(new AreaChart.Data<Number, Number>(0d, 0d)); 
     areaChart.getData().add(series1); 

     series2 = new AreaChart.Series<>(); 
     series2.getData().add(new AreaChart.Data<Number, Number>(0d, 0d)); 
     areaChart.getData().add(series2); 

     return areaChart; 
    } 

    public void play() { 
     animation.play(); 
    } 

    @Override 
    public void stop() { 
     animation.pause(); 
    } 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     primaryStage.setScene(new Scene(createContent())); 
     primaryStage.show(); 
     play(); 
    } 

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

我試過你的應用程序,它在啓動時工作正常。但是,如果我點擊應用程序窗口的最大化按鈕,應用程序沒有響應。但面積不斷更新。 – pavankumar

+0

然後問題出在你的系統上。代碼工作得很好,即使處於最大化狀態。你在用什麼JDK?嘗試將UPDATE_INTERVAL_MS更改爲更高的值以查看它是否是性能問題。說到這些,Taskmanager性能圖表顯示了什麼?我目前的懷疑是你的系統太慢而無法滿足要求。 – Roland

+0

是的,它在高配置系統中工作正常。謝謝 – pavankumar