我有一个带有JafavaFx的表视图,用于每秒向用户显示货币。一切正常,但是当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();
我的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;
}
这就是结果:
我的问题是:
非常感谢!
发布于 2013-02-27 10:14:01
看起来您正在某些方法中执行I/O操作(至少在它们的签名中有一个throws IOException
)。
您不应该在JavaFX应用程序线程上执行任何I/O操作,因为该线程处理用户界面。如果您确实在JavaFX应用程序线程上执行I/O操作,那么您最终将阻塞线程,程序将显示对用户没有响应。
您要做的是异步地将数据从服务器获取到客户端。要做到这一点,您应该使用JavaFX并发实用程序,如任务和服务。另一件需要注意的事情是,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中的,所以这里或那里可能会有一些小错误,但我认为它给出了这个想法的要点。
您可能会注意到,将url传递到服务以使其不能在不同线程上被修改的所有技巧都是直接从Service
javadoc示例复制的。另外,如果您的url只是一个静态的东西,不会改变,那么您可以将它编码为一个static final
常量,而不必将它作为一个变量参数。
注意,使用TableView不是问题(您可以使用网格或任何其他控件,如果阻止,您仍然会遇到问题)。
如果上面的工作似乎是为了进行服务器调用和获取一些数据而做的大量工作,那么应该注意的是,JavaFX (目前)只是这些类型的服务的低级提供者。有第三方库(如DataFX ),它们提供高级服务,用于异步从各种源获取数据,从各种格式(如xml和json )解析数据,并填充各种JavaFX控件(如TableViews和ListViews )。
发布于 2013-02-26 07:04:03
您可能对使用高级图表感兴趣,特别是下面的示例:http://www.highcharts.com/stock/demo/dynamic-update
https://stackoverflow.com/questions/15083182
复制相似问题