2013-02-26 1 views
3

У меня есть одно табличное представление с JafavaFx для отображения в пользовательских валютах каждую секунду. Каждая вещь работает нормально, но когда tableView пытается перезагрузить данные, она останавливает что-то миллисекунды, я имею в виду морозильник и выглядит не очень красиво. Я не мог удалить это поведение код, который я использую в данный момент является то, что:TableView Live Javafx

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(); 

Моего TableColum

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") 
      ); 

В другом классе для добавления столбцов у меня есть одна функции так:

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; 
} 

и это результат:

enter image description here

Мои вопросы:

  • я должен использовать другой компонент, как сетки, ... для сделать этот тип действия?
  • если возможно, что я должен делать?

Большое спасибо!

+0

Что такое код для getObservableList? Зачем заменять весь список, а не просто обновлять свойства, которые необходимо обновить? Вы делаете что-нибудь интенсивное на клеточных фабриках? Можете ли вы предоставить минимальный исполняемый пример? Кто большой список и таблица (num entries и num cols)? Обновите свой вопрос с помощью этих ответов. – jewelsea

+0

Извините, может быть, я совсем новый. Когда вы говорите об обновлении ... Я должен перебрать все представление таблицы, и если я найду какие-либо изменения, обновить их? –

ответ

1

Похоже, что вы делаете I/O в некоторых из ваших методов (по крайней мере, имеют в своей подписи на throws IOException).

Вы не должны делать ввода-вывода в приложении JavaFX Application Thread, так как этот поток обрабатывает пользовательский интерфейс. Если вы выполняете ввод-вывод в приложении JavaFX Application Thread, то в конечном итоге вы заблокируете поток, и программа окажется невосприимчивой к пользователю.

Что вы хотите сделать, это асинхронно получать данные с сервера клиенту. Для этого вы должны использовать утилиты параллельного использования JavaFX, такие как Task и Service. Еще одна вещь, о которой нужно помнить, заключается в том, что ваш поток ввода-вывода ввода/вывода не должен напрямую обновлять ваш пользовательский интерфейс (или даже косвенно 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 без компиляции или тестирования, так что вы можете иметь некоторые незначительные ошибки здесь или там, но я думаю, это дает вам суть идеи.

Вы можете заметить, что вся эта сложность в передаче URL-адреса службе, чтобы ее нельзя было изменить в другом потоке, просто копируется прямо из примера javadoc Service. Также, если ваш URL-адрес - это просто статическая вещь, которая никогда не изменяется, тогда вы можете закодировать ее как константу static final и не беспокоить ее как параметр переменной.

Обратите внимание, что использование TableView не является проблемой (вы можете использовать Grid или любой другой элемент управления, и у вас все еще будет проблема, если вы заблокируете Thread Application Java).

Если вышеприведенная работа представляет собой большую работу только для того, чтобы сделать серверный вызов и получить некоторые данные, следует отметить, что JavaFX (в настоящее время) является поставщиком услуг этих типов для низкого уровня. Существуют сторонние библиотеки, такие как DataFX, которые предоставляют услуги высокого уровня для выполнения таких задач, как асинхронное получение данных из разных источников, разбор его из различных форматов, таких как xml и json, и заполнение различных элементов управления JavaFX, таких как TableViews и ListViews.

+0

Guauuu !! мерси !! позвольте мне попробовать :) –

+0

Это исправить мою проблему :)! Спасибо ! –

-1

Вы можете быть заинтересованы в использовании Highcharts, в частности, пример: http://www.highcharts.com/stock/demo/dynamic-update

+0

Умм, но это сценарий java, я знаю, что эта библиотека классная. Но я не понимаю, как это может мне помочь с javaFx –