5

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

在此处输入图像描述

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

  public static class ProgressBarTableCell<S, T> extends TableCell<S, T> {

        private final ProgressBar progressBar;
        private ObservableValue<T> 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的应用程序的用户界面在连续几次后冻结。有没有其他方法可以在后台线程中调用updateProgressbar()在特定时间间隔后自动触发并且不会冻结我JavaFX的应用程序的 UI?

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

已编辑 -

根据安迪先生的建议,直到我更新了我的代码但仍然没有运气 -

TableColumn tableColumn_Progress = new TableColumn("Progress");
        tableColumn_Progress.setCellValueFactory(new PropertyValueFactory<QueueData, Double>("progressBar"));
        tableColumn_Progress.setPrefWidth(100);

        Callback<TableColumn<QueueData, Double>, TableCell<QueueData, Double>> attachmentCellFactory = //
                new Callback<TableColumn<QueueData, Double>, TableCell<QueueData, Double>>() {
            @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,但没有运气。

4

2 回答 2

5

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

我知道您的实现已经很远了,但是 JavaFX 服务类已经实现了一个进度功能,您可以对其进行更新,这比您现在的操作要简单得多。

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

还要确保你正在处理你的线程,这很容易检查。在 Eclipse 中进行调试,在调试透视图中,它将向您显示线程列表,确保它不会无休止地增长。

对于调度 Runnable 签出 ScheduledExecutor 类,您可以使用 Executors.newScheduledThreadPool(numOfThreads) 轻松创建它。

于 2012-12-12T21:51:35.623 回答
5

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

将此更新为 -

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

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

于 2012-12-14T07:27:43.597 回答