Contrôle automatique de la dernière colonne dans JavaFX TableView

Aperçu

J'avais du mal à contrôler la largeur de la colonne de JavaFX TableView, donc une note sur la façon de le gérer.

J'ai essayé de définir la dernière colonne sur le contrôle automatique afin que la colonne soit remplie sur toute la largeur du tableau.

ColumnResizePolicy Il existe un mécanisme appelé ColumnResizePolicy pour contrôler la largeur de colonne de JavaFx TableView. Cela semble être un mécanisme qui détermine comment contrôler la largeur de la colonne au moment du dessin initial et de l'ajustement de la largeur de la colonne.

Deux types sont préparés par défaut

constant Aperçu
UNCONSTRAINED_RESIZE_POLICY Il n'y a pas de contrôle particulier et la largeur de la colonne est traitée au fur et à mesure que l'utilisateur la déplace.
CONSTRAINED_RESIZE_POLICY Largeur de colonne égale lors du dessin initial et traitement uniforme des autres colonnes lors du développement et de la réduction des colonnes

Si un autre traitement unique est requis, il doit être implémenté, et en réalité c'est la classe Callback.

public final void setColumnResizePolicy(Callback<ResizeFeatures, Boolean> callback)

En cela, il semble que cela se réalise en changeant la largeur de chaque colonne et en retournant true si cela réussit.

Ce que je souhaitais personnellement, c'était le contrôle automatique de la largeur de la dernière colonne, ce que je voulais réaliser: --Lors du dessin initial, lors du redimensionnement de la fenêtre, je veux adapter la dernière colonne à la largeur de la fenêtre (volet) --Je souhaite adapter la dernière colonne à la largeur de la fenêtre (volet) même en double-cliquant sur ajustement automatique.

J'ai regardé autour de TableView de JavaFx et j'ai cherché quelque chose qui ne pouvait pas être fait, mais il semble que ce ne soit pas la valeur par défaut, alors j'ai abandonné et mis en œuvre. J'ai réussi à obtenir le comportement souhaité. Je ne l'ai pas examiné en détail, mais cela ne semble pas être un problème pour vérifier l'opération.

public class ResizePolicy {

    public static <S> void setLastColumnResizePolicy(TableView<S> tableView) {
        //Définir la politique de redimensionnement
        tableView.setColumnResizePolicy(prop -> {
            if (prop.getTable().getWidth() < 0) {
                return false;
            }
            resizeTargetColumn(prop);
            resizeLastColumn(prop);
            return true;
        });

        //Ajouter un processus de redimensionnement après l'ajustement automatique en double-cliquant
        addResizeBorderDoubleClickedEvent(tableView);
    }

    private static void resizeTargetColumn(TableView.ResizeFeatures<?> prop) {
        var targetColumn = prop.getColumn();
        var delta = prop.getDelta();

        if (delta != 0 && targetColumn.isResizable()) {
            var newWidth = targetColumn.getWidth() + delta;

            //Définissez la largeur finale en tenant compte de la largeur maximale et de la largeur minimale
            if (newWidth > targetColumn.getMaxWidth()) {
                targetColumn.setPrefWidth(targetColumn.getMaxWidth());
            } else if (newWidth < targetColumn.getMinWidth()) {
                targetColumn.setPrefWidth(targetColumn.getMinWidth());
            } else {
                targetColumn.setPrefWidth(newWidth);
            }
        }
    }

    private static void resizeLastColumn(TableView.ResizeFeatures<?> prop) {
        var table = prop.getTable();
        // -18.Si vous ne définissez pas 0, une barre de défilement apparaît. 18.0 est simplement décidé en regardant l'écran
        var tableContentWidth = table.getWidth() - 18.0;

        //Calculez la largeur de la dernière colonne à partir de la valeur totale autre que la dernière colonne et de la largeur du tableau
        var columns = table.getVisibleLeafColumns();
        var columnsOfExcludedLastColumn = columns.stream().limit(columns.size() - 1);
        var widthsOfExcludedLastColumn = columnsOfExcludedLastColumn.map(TableColumnBase::getWidth);
        var lastColumnWidth = widthsOfExcludedLastColumn
                .reduce(tableContentWidth, (remainingWidth, columnWidth) -> remainingWidth - columnWidth);

        if (lastColumnWidth > 0) {
            var lastColumn = columns.get(columns.size() - 1);
            lastColumn.setPrefWidth(lastColumnWidth);
        }
    }

    private static <S> void addResizeBorderDoubleClickedEvent(TableView<S> tableView) {
        //Puisque la peau est nulle lors du dessin de l'écran, enregistrez ce que vous voulez faire en tant qu'événement
        tableView.skinProperty().addListener((observable, oldValue, newValue) -> {
            var tableViewSkin = (TableViewSkin<?>) newValue;
            var tableViewSkinNodes = tableViewSkin.getChildren().stream();
            var tableHeaderRowNode = tableViewSkinNodes.filter(node -> node instanceof TableHeaderRow).findFirst();

            tableHeaderRowNode.ifPresent((node) -> {
                var tableHeaderRow = (TableHeaderRow) node;
                var tableColumnHeader = (NestedTableColumnHeader) tableHeaderRow.getChildren().get(1);

                tableColumnHeader.addEventFilter(MouseEvent.MOUSE_PRESSED, mouseEvent -> {
                    //Pour les changements de largeur de colonne, la ligne carrée est la cible réelle de l'événement
                    //Et pour l'ajustement automatique double-cliquez
                    if (isRectangle(mouseEvent) && isDoubleClick(mouseEvent)) {

                        //Trouvez la colonne cible à partir de la position de la ligne carrée cliquée et de la largeur de la colonne
                        var rectangle = (Rectangle) mouseEvent.getTarget();
                        var columnPosition = 0.0;
                        for (var column : tableView.getColumns()) {
                            columnPosition += column.getWidth();
                            if (rectangle.getLayoutX() < columnPosition) {
                                //Si vous exécutez la politique de redimensionnement à ce moment,
                                //Comme la largeur n'a pas été modifiée par l'ajustement automatique, l'exécution réelle sera reportée.
                                Platform.runLater(() -> {
                                    var columnResizePolicy = tableView.getColumnResizePolicy();
                                    columnResizePolicy.call(new TableView.ResizeFeatures<S>(tableView, column, -0.1));
                                });
                                break;
                            }
                        }
                    }
                });
            });
        });
    }

    private static boolean isRectangle(MouseEvent mouseEvent) {
        return mouseEvent.getTarget() instanceof Rectangle;
    }

    private static boolean isDoubleClick(MouseEvent mouseEvent) {
        return mouseEvent.getClickCount() == 2 && mouseEvent.isPrimaryButtonDown();
    }

}

En fait, j'ai essayé d'en faire une classe au lieu de statique, mais j'ai reçu un avertissement en raison d'un problème générique, et j'ai pensé que ce serait une bonne idée de le supprimer avec SuppressWarnings, alors j'en ai fait une méthode statique. .. ..

ResizeFeatures est une classe générique, mais la méthode setColumnResizePolicy la gère brut, donc si vous faites la déclaration de type vous-même, elle ne sera pas acceptée avec une erreur de type. J'ai l'impression de recevoir un avertissement si je ne tape pas.

Pourquoi cela arrive-t-il? .. ..

Recommended Posts

Contrôle automatique de la dernière colonne dans JavaFX TableView
Mémo organisé dans la tête (syntaxe Java --Control)