JavaFX UI冻结问题

我试图显示每项任务的进度和状态。 每个任务一行代表TableView 。 每个任务在每个Thread执行并行执行。 请参考TableView图片。

在此处输入图像描述

对于“Progress” TableColumn我将Cell Factory设置为渲染“ProgressBar”。

  public static class ProgressBarTableCell extends TableCell { private final ProgressBar progressBar; private ObservableValue ov; public ProgressBarTableCell() { this.progressBar = new ProgressBar(); progressBar.setPrefHeight(23); setAlignment(Pos.CENTER); } @Override public void updateItem(T item, boolean empty) { super.updateItem(item, empty); if (item == null) { setGraphic(null); setText(null); } else { if (item.toString().equalsIgnoreCase("Processing")) { Platform.runLater(new Runnable() { @Override public void run() { if (getGraphic() == null) { setGraphic(progressBar); progressBar.setProgress(-1); } else { ProgressBar objpProgressBar = (ProgressBar) getGraphic(); objpProgressBar.setProgress(-1); } setContentDisplay(ContentDisplay.GRAPHIC_ONLY); } }); } else { Platform.runLater(new Runnable() { @Override public void run() { if (getGraphic() == null) { setGraphic(progressBar); progressBar.setProgress(0); } else { ProgressBar objpProgressBar = (ProgressBar) getGraphic(); objpProgressBar.setProgress(0); } setContentDisplay(ContentDisplay.GRAPHIC_ONLY); } }); } } } } 

TableView没有显示任务的更新状态和进度,所以我在后台定期运行一个线程,当我调用startUpdatingTableProgress()时它会修改TableView当我调用stopUpdatingTableProgress()时会停止。

  public void stopUpdatingTableProgress() { keepUpdating = false; } public void startUpdatingTableProgress() { keepUpdating = true; TableProgressBarUpdator tpu = new TableProgressBarUpdator(table); tpu.start(); } class TableProgressBarUpdator implements Runnable { TableView table; public TableProgressBarUpdator(TableView fxtable) { table = fxtable; } public void start() { new Thread(this).start(); } public void run() { while (keepUpdating) { try { updateProgressbar(); Thread.sleep(1000); } catch (Exception e) { LogHandler.doErrorLogging("Error while updating tables cell", e); } } LogHandler.doDebugLogging("Table process repainting is completed."); } private void updateProgressbar() throws Exception { Platform.runLater(new Runnable() { @Override public void run() { ((TableColumn) table.getColumns().get(0)).setVisible(false); ((TableColumn) table.getColumns().get(0)).setVisible(true); } }); } } 

但现在我的JavaFX应用程序的UI连续几次冻结。 是否有任何替代方法可以在后台线程中调用updateProgressbar(),该后台线程在特定时间间隔后自动触发并且不冻结我的JavaFX App的UI?

我不知道我是否正确地更新每个任务在一个单独的线程中运行的任务的状态。 如果我想在javafx.concurrent package的帮助下实现这个,那么有人可以向我展示一些指导或流程吗? 什么将进入任务和什么将进入服务类? 我如何安排它来更新进度条? 仅供参考:一次只允许5个线程并行执行。

编辑 –

根据Andy Till先生的建议,我已经更新了我的代码,但仍然没有运气 –

 TableColumn tableColumn_Progress = new TableColumn("Progress"); tableColumn_Progress.setCellValueFactory(new PropertyValueFactory("progressBar")); tableColumn_Progress.setPrefWidth(100); Callback<TableColumn, TableCell> attachmentCellFactory = // new Callback<TableColumn, TableCell>() { @Override public TableCell call(final TableColumn param) { final ProgressBarTableCell cell = new ProgressBarTableCell() { @Override public void updateItem(Object item, boolean empty) { super.updateItem(item, empty); } }; return cell; } }; tableColumn_Progress.setCellFactory(attachmentCellFactory); 

在QueueData类中 –

 DoubleProperty progressBar = null; public DoubleProperty progressBarProperty() { return progressBar; } public Double getprogressBar() { return progressBar.get(); } public void setprogressBar(Double sType) { this.progressBar = new SimpleDoubleProperty(sType); } 

而不是调用任何后台线程来更新UI但没有运气。

你的’QueueData’类应该有设置现有进度的double属性的方法,你似乎每次都在setprogressBar(Double sType)方法中设置进度状态时创建新的SimpleDoubleProperty。

将此更新为 –

  public void setprogressBar(Double sType) { this.progressBar.set(sType); } 

只需在开始时创建progressBar对象,然后更新现有对象。

据我了解您的代码,您正在翻转可见性以触发表格单元格上的updateItem方法? 这意味着任何数量的线程都可能尝试每秒更改可见性并无休止地重新绘制。

我知道你已经完成了很多实现,但是JavaFX服务类已经实现了一个可以更新的进度function,这比你现在的工作简单得多。

拥有一个进程double属性会更加简单和高效,您可以从线程更新并将其绑定到ProgressBar.progressProperty(),以便一切都会自动更新。 这是Service类的工作方式,但很容易实现。

还要确保你正在处理你的线程,这很容易检查。 在eclipse中调试,在调试透视图中,它将显示线程列表,确保它不会无限增长。

为了安排Runnable checkout ScheduledExecutor类,您可以使用Executors.newScheduledThreadPool(numOfThreads)轻松创建它。