3

毎秒ユーザー通貨に表示するために、JafavaFx を使用したテーブルビューが 1 つあります。すべてが正常に機能しますが、tableView がデータをリロードしようとすると、ミリ秒単位で停止します。フリーザーを意味し、あまり良くありません。この動作を削除できませんでした。この瞬間に使用するコードは次のとおりです。

setCache(true);

        setItems(getObservableList());
        Timeline animation = new Timeline();
        animation.getKeyFrames().add(new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                setItems(getObservableList());                  
            }
        }));
        animation.setCycleCount(Animation.INDEFINITE);
        animation.play();

マイ テーブル列

getColumns().addAll(
            getStringField("id","Tikect"), 
            getStringField("currency","Symbol"), 
            getStringField("type","S/B"), 
            getDoubleField("amount","Amt (k)"), 
            getDoubleField("open","Open"), 
            getDoubleField("close","Close"),
            getDoubleField("stop","Stop"), 
            getDoubleField("limit","Limit"), 
            getDoubleField("pl","P/L"), 
            getDoubleField("gpl","Gross P/L")
            );

列を追加するための他のクラスには、次のような関数が1つあります。

    public static TableColumn<BaseModel, String> getStringField(String idColumn,String nameColumn) {
    TableColumn<BaseModel, String> column = new TableColumn<BaseModel, String>(idColumn);
    column.setCellValueFactory(new PropertyValueFactory<BaseModel, String>(idColumn));
    column.setMinWidth(100);
    column.setText(nameColumn);

    return column;
}

私の ObservableList は次のとおりです。

public ObservableList<BaseModel> getObservableList() throws IOException {
    ObservableList<BaseModel> oTransacctions = FXCollections.observableArrayList();

    JsonFactory factory = new JsonFactory();
    JsonParser jp = factory.createJsonParser(new URL(getURL()));

    JsonToken token = jp.nextToken();

    while (token != JsonToken.START_ARRAY) {
        token = jp.nextToken();
    }

    while (token != JsonToken.END_ARRAY) {
        token = jp.nextToken();

        if (token == JsonToken.START_OBJECT) {
            Transaction transaction = parseTransacction(jp);
            oTransacctions.add(transaction);
        }
    }

    return oTransacctions;
}

private Transaction parseTransacction(JsonParser jp) throws IOException {
    Transaction transaction = new Transaction();
    JsonToken token = jp.nextToken();

    while (token != JsonToken.END_OBJECT) {
        if (token == JsonToken.START_OBJECT) {
            while (token != JsonToken.END_OBJECT) {
                token = jp.nextToken();
            }
        }

        if (token == JsonToken.FIELD_NAME) {
            String fieldname = jp.getCurrentName();

            if ("id".equals(fieldname)) {
                jp.nextToken();
                transaction.setId(jp.getText());
            }
            if ("currency".equals(fieldname)) {
                jp.nextToken();
                transaction.setCurrency(jp.getText());
            }
            if ("type".equals(fieldname)) {
                jp.nextToken();
                transaction.setType(jp.getText());
            }
            if ("amount".equals(fieldname)) {
                jp.nextToken();
                transaction.setAmount(jp.getValueAsDouble());
            }
            if ("open".equals(fieldname)) {
                jp.nextToken();
                transaction.setOpen(jp.getValueAsDouble());
            }
            if ("stop".equals(fieldname)) {
                jp.nextToken();
                transaction.setStop(jp.getValueAsDouble());
            }
            if ("limit".equals(fieldname)) {
                jp.nextToken();
                transaction.setLimit(jp.getValueAsDouble());
            }
            if ("created_at".equals(fieldname)) {
                jp.nextToken();
                // transaction.setCreated_at(new Date(jp.getText()));
            }
            if ("pl".equals(fieldname)) {
                jp.nextToken();
                transaction.setPl(jp.getValueAsDouble());
            }
            if ("gpl".equals(fieldname)) {
                jp.nextToken();
                transaction.setGpl(jp.getValueAsDouble());
            }
            if ("close".equals(fieldname)) {
                jp.nextToken();
                transaction.setClose(jp.getDoubleValue());
            }
        }
        token = jp.nextToken();
    }

    return transaction;
}

これが結果です:

ここに画像の説明を入力

私の質問は:

  • このタイプのアクションを実行するには、グリッドなどの他のコンポーネントを使用する必要がありますか?
  • 可能な場合、私は何をすべきですか?

どうもありがとう !

4

2 に答える 2

3

一部のメソッドで I/O を行っているようです (少なくともthrows IOExceptionシグネチャに a があります)。

JavaFX アプリケーション スレッドはユーザー インターフェイスを処理するため、JavaFX アプリケーション スレッドで I/O を実行しないでください。JavaFX アプリケーション スレッドで I/O を実行すると、最終的にスレッドがブロックされ、プログラムがユーザーに応答しないように見えます。

やりたいことは、サーバーからクライアントに非同期でデータをフェッチすることです。これを行うには、 TaskServiceなどの JavaFX 同時実行ユーティリティを利用する必要があります。注意すべきもう 1 つのことは、I/O フェッチ スレッドが UI を直接更新してはならないことです (またはObservableListテーブルを間接的に更新することさえありません)。

あなたの場合、私は以下のコードのようなことをします:

final ForexService forex = new ForexService();
forex.setUrl(getUrl()); // getUrl() is some method your application provides 
forex.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
  @Override public void handle(WorkerStateEvent event) {
    setItems(forex.getValue());     
    forex.reset();             
  }
}           
forex.setOnFailed(new EventHandler<WorkerStateEvent>() {
  @Override public void handle(WorkerStateEvent event) {
    // exception handling with forex.getException()   
    forex.reset();             
  }
}           
...
Timeline animation = new Timeline();
animation.getKeyFrames().add(new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>() {
  @Override public void handle(WorkerStateEvent event) {
    if (Worker.State.READY == forex.getState()) {
      forex.start();
    }
  } 
}));
animation.setCycleCount(Animation.INDEFINITE);
animation.play();
...
public static class ForexService extends Service<ObservableList<BaseModel>> {
  private StringProperty url = new SimpleStringProperty(this, "url");
  public final void setUrl(String value) { url.set(value); }
  public final String getUrl() { return url.get(); }
  public final StringProperty urlProperty() { return url; }

  protected Task createTask() {
    final String _url = getUrl();
    return new Task<ObservableList<BaseModel>>() {
      protected String call() throws Exception {
        // getObservableList is the function which actually fetches the
        // data from the server and processes it into an ObservableList
        // which can later be fed to a TableView.
        // This function is essentially the same as the function
        // supplied in your question.
        return getObservableList(new URL(_url));
      }
    };
  }
}

上記のコードは、コンパイルやテストを行わずに StackOverflow に入力しただけなので、あちこちで小さなエラーが発生する可能性がありますが、アイデアの要点はわかると思います。

Service別のスレッドで URL を変更できないようにサービスに URL を渡すというトリッキーさはすべて、 javadoc の例からそのままコピーしただけであることに気付くかもしれません。また、URL が変更されない静的なものである場合は、それをstatic final定数としてコーディングし、わざわざ変数パラメーターにする必要はありません。

TableView の使用は問題ではないことに注意してください (Grid またはその他のコントロールを使用できますが、Java アプリケーション スレッドをブロックすると問題が発生します)。

上記がサーバー呼び出しを行ってデータを取得するためだけに多くの作業のように思われる場合、JavaFX は (現在) これらの種類のサービスの低レベルのサプライヤーにすぎないことに注意してください。さまざまなソースからのデータの非同期フェッチ、xml や json などのさまざまな形式からのデータの解析、TableViews や ListViews などのさまざまな JavaFX コントロールへの入力などを行うための高レベルのサービスを提供するDataFXなどのサードパーティ ライブラリがあります。

于 2013-02-27T10:14:01.100 に答える
-1

Highcharts の使用に興味があるかもしれません。特に次の例をご覧ください: http://www.highcharts.com/stock/demo/dynamic-update

于 2013-02-26T07:04:03.550 に答える