TableView Live Javafx
我有一个与JafavaFx的TableView每秒向用户显示货币。每一件事情都很好,但是当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;
}
,这是结果:
我的问题是:
- 我应该用其他的组件如电网,...对于做这种类型的行动?
- 如果可行我该怎么办?
非常感谢!
看起来你是在你的一些方法做I/O(至少在他们的签名throws IOException
)。
由于该线程处理用户界面,因此不应该在JavaFX应用程序线程上执行任何I/O。如果您确实在JavaFX应用程序线程上执行了I/O,那么您将最终阻止该线程,并且该程序对用户显示无响应。
你想要做的是异步地从服务器获取数据到客户端。为此,您应该使用JavaFX并发实用程序,例如Task和Service。还有一点需要注意的是,你的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));
}
};
}
}
上面的代码只是输入到*上没有编译或测试,所以你可能有一些小错误在这里或那里,但我认为它给你的想法的主旨。
您可能会注意到,将url传递给服务以至于无法在其他线程上修改的所有技巧只是从Service
javadoc示例中直接复制而来。另外,如果你的url只是一些永不改变的静态东西,那么你可以将它编码为一个常量,而不用费心使它成为一个可变参数。
请注意,使用TableView不是问题(您可以使用Grid或任何其他控件,并且如果阻止Java应用程序线程,您仍然会遇到问题)。
如果上面的工作看起来像只是为了进行服务器调用和获取一些数据而做的很多工作,那么应该注意的是,JavaFX目前只是这些类型的服务的低级别供应商。有第三方库,如DataFX,它们提供高级服务,用于执行诸如异步获取各种来源的数据,解析来自xml和json等各种格式的内容以及填充各种JavaFX控件(如TableView和ListViews)。
Guauuu! MERCI!让我试试:) – 2013-02-27 11:50:28
解决我的问题:)!谢谢 ! – 2013-02-27 14:12:35
你可能有兴趣使用Highcharts,特别是这个例子:http://www.highcharts.com/stock/demo/dynamic-update
嗯,但这是java脚本,我知道这个库很酷。但我不明白它如何可以帮助我用javaFx – 2013-02-26 07:11:26
getObservableList的代码是什么?为什么要替换整个列表而不是只更新需要更新的属性?你在细胞工厂做密集的工作吗?你能提供一个最小的可执行示例吗?谁是名单和表格(数字和数字)?请用这些答案更新您的问题。 – jewelsea 2013-02-27 02:55:27
对不起,也许我很新。当你谈论更新...我应该迭代所有的表视图,如果我发现有任何更改更新这些? – 2013-02-27 06:22:22