首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >TableView Live

TableView Live
EN

Stack Overflow用户
提问于 2013-02-26 06:57:34
回答 2查看 2.6K关注 0票数 3

我有一个带有JafavaFx的表视图,用于每秒向用户显示货币。一切正常,但是当tableView试图重新加载数据时,它停止了几毫秒的时间,我的意思是冷冻机,看起来不太酷。我无法删除这种行为,我在这一刻使用的代码是:

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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")
            );

在添加列的其他类中,我有一个类似的函数:

代码语言:javascript
运行
复制
    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是:

代码语言:javascript
运行
复制
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;
}

这就是结果:

我的问题是:

  • 我应该使用其他组件比如网格..。为了做这种行为?
  • 如果是肯定的,我该怎么做?

非常感谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-02-27 10:14:01

看起来您正在某些方法中执行I/O操作(至少在它们的签名中有一个throws IOException )。

您不应该在JavaFX应用程序线程上执行任何I/O操作,因为该线程处理用户界面。如果您确实在JavaFX应用程序线程上执行I/O操作,那么您最终将阻塞线程,程序将显示对用户没有响应。

您要做的是异步地将数据从服务器获取到客户端。要做到这一点,您应该使用JavaFX并发实用程序,如任务服务。另一件需要注意的事情是,I/O取取线程不应该直接更新UI (甚至不应该间接更新支持表的ObservableList )。

在您的例子中,我将执行如下代码:

代码语言:javascript
运行
复制
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传递到服务以使其不能在不同线程上被修改的所有技巧都是直接从Service javadoc示例复制的。另外,如果您的url只是一个静态的东西,不会改变,那么您可以将它编码为一个static final常量,而不必将它作为一个变量参数。

注意,使用TableView不是问题(您可以使用网格或任何其他控件,如果阻止,您仍然会遇到问题)。

如果上面的工作似乎是为了进行服务器调用和获取一些数据而做的大量工作,那么应该注意的是,JavaFX (目前)只是这些类型的服务的低级提供者。有第三方库(如DataFX ),它们提供高级服务,用于异步从各种源获取数据,从各种格式(如xml和json )解析数据,并填充各种JavaFX控件(如TableViews和ListViews )。

票数 3
EN

Stack Overflow用户

发布于 2013-02-26 07:04:03

您可能对使用高级图表感兴趣,特别是下面的示例:http://www.highcharts.com/stock/demo/dynamic-update

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15083182

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档