TableView的两个不同的行工厂

时间:2016-01-15 11:24:36

标签: java javafx

在我的程序中有一个TableView,我想注册两个不同的行工厂来根据内容格式化我的行。

这是我的工厂:

private void highlightReportRowsIfImportant() {
        tv_berichte.setRowFactory(new Callback<TableView<DatabaseReport>, TableRow<DatabaseReport>>() {
            @Override
            public TableRow<DatabaseReport> call(TableView<DatabaseReport> tableView) {
                final TableRow<DatabaseReport> row = new TableRow<DatabaseReport>() {
                    @Override
                    protected void updateItem(DatabaseReport report, boolean empty) {
                        super.updateItem(report, empty);
                        if (report != null) {
                            if (report.getReport_art().contains("!!!")) {
                                setStyle("-fx-background-color: #FF0000;");
                            } else {
                                setStyle("");
                            }
                        } else {
                            setStyle("");
                        }
                    }
                };
                reports.addListener(new ListChangeListener<DatabaseReport>() {
                    @Override
                    public void onChanged(ListChangeListener.Change<? extends DatabaseReport> change) {
                        if (row.getItem() != null) {
                            if (row.getItem().getReport_art().contains("!!!")) {
                                row.setStyle("-fx-background-color: #FF0000;");
                            } else {
                                row.setStyle("");
                            }
                        } else {
                            row.setStyle("");
                        }
                    }
                });
                return row;
            }
        });
    }

这是另一个:

private void registerDragAndDropReportListener(TableView view) {
    view.setRowFactory(tv -> {
        TableRow<DatabaseReport> row = new TableRow<>();

        row.setOnDragDetected(event -> {
            if (!row.isEmpty()) {
                Dragboard db = row.startDragAndDrop(TransferMode.COPY);
                db.setDragView(row.snapshot(null, null));
                ClipboardContent cc = new ClipboardContent();
                cc.putString(row.getItem().getReport_content());
                db.setContent(cc);
                event.consume();
            }
        });

        row.setOnDragOver(event -> {
            Dragboard db = event.getDragboard();
            if (db.hasContent(DataFormat.PLAIN_TEXT)) {
                event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
                event.consume();
            }
        });

        row.setOnDragDropped(event -> {
            Dragboard db = event.getDragboard();
            if (db.hasContent(DataFormat.PLAIN_TEXT)) {
                reportFlowController.addNewReport(username, getSqlTimeStamp().toString(), this.txt_adressnummer.getText(), reports, db.getString());
                event.setDropCompleted(true);
                event.consume();
            }
        });

        return row;
    });
}

现在如果我这样注册工厂:

registerDragAndDropReportListener(tv_berichte);
highlightReportRowsIfImportant();

仅使用最后一个。

请您解释一下我如何注册这两个?

2 个答案:

答案 0 :(得分:1)

您无法注册多个行工厂,尝试这样做是没有意义的。 TableView使用其行工厂在需要时创建TableRow对象(通常在屏幕上首次布局时,如果它垂直增长并且需要显示更多行,则可能稍后);记住行工厂只是一个提供TableRow个对象的函数。如果注册了两个或更多行工厂,则TableView将没有选择使用哪个工厂的机制。

您可以做的是定义一个使用现有行工厂生成行的行工厂。这有效地替换了现有的行工厂,并为其添加了额外的功能:

private void registerDragAndDropReportListener(TableView<DatabaseReport> view) {

    Callback<TableView<DatabaseReport>, TableRow<DatabaseReport>> existingRowFactory 
            = view.getRowFactory();

    view.setRowFactory(tv -> {



        TableRow<DatabaseReport> row ;
        if (existingRowFactory == null) {
            row = new TableRow<>();
        } else {
            row = existingRowFactory.call(view);
        }

        row.setOnDragDetected(event -> {
            if (!row.isEmpty()) {
                Dragboard db = row.startDragAndDrop(TransferMode.COPY);
                db.setDragView(row.snapshot(null, null));
                ClipboardContent cc = new ClipboardContent();
                cc.putString(row.getItem().getReport_content());
                db.setContent(cc);
                event.consume();
            }
        });

        row.setOnDragOver(event -> {
            Dragboard db = event.getDragboard();
            if (db.hasContent(DataFormat.PLAIN_TEXT)) {
                event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
                event.consume();
            }
        });

        row.setOnDragDropped(event -> {
            Dragboard db = event.getDragboard();
            if (db.hasContent(DataFormat.PLAIN_TEXT)) {
                reportFlowController.addNewReport(username, getSqlTimeStamp().toString(), this.txt_adressnummer.getText(), reports, db.getString());
                event.setDropCompleted(true);
                event.consume();
            }
        });

        return row;
    });
}

使用此方法,registerDragAndDropReportListener方法将现有的行工厂替换为向现有行工厂添加其他功能的方法,我认为这就是您想要的。因此,在这种情况下,您首先会调用原始highlightRowsIfImportant方法,然后调用显示的新registerDragAndDropReportListener方法。

您可以对其他方法进行类似的更改,以便您可以按所需的任何顺序调用这两种方法。请注意,在这种情况下,确保只调用一次方法非常重要。

答案 1 :(得分:0)

这是我的解决方案,在同一行工厂中使用两个侦听器并使用相同的行对象。在你发布你的awnser James_D之后,我很清楚。我不能注册其中的两个,这应该是handelt ...首先想一想,然后编写代码......

.... 
$scope.$data = [ ...]

function ativoOrPerfil(item) {
  return item.ativo == filtroAtivo && (filtroPerfil == null || item.perfil == filtroPerfil )

}

function updateFiltered() {
   $scope.$dataFiltered = $scope.$data.filter(ativoOrPerfil)
}

$scope.$watch('filtroAtivo', updateFiltered)
$scope.$watch('filtroPerfil', updateFiltered)