为什么TableColumn的宽度绑定不起作用?

时间:2014-09-30 07:00:37

标签: binding tableview javafx-8 tablecolumn

我想将TableView第二列的宽度与TableView的宽度绑定。

我的自定义TableView:

public class CustomTableView<T> extends
        TableView<ObservableList<Pair<String, Object>>> implements Cloneable {
    private static Logger logger = Logger.getLogger(CustomTableView.class);

    private double prefWidth; // optionnel

    private double minWidth; // optionnel

    private double maxWidth; // optionnel

    private double height; // optionnel

    private List<InfoColumnBean> cols; // optionnel

    private ObservableList<ObservableList<Pair<String, Object>>> data; // optionnel

    private boolean withContextMenu; // optionnel

    private ContextMenu menu; // optionnel

    private String title; // obligatoire

    private int titleWidth; // optionnel

    private Label placeHolder; // optionnel

    @SuppressWarnings("unchecked")
    public CustomTableView(CustomTableViewBuilder<T> builder) {
        super();

        // apparence tableau
        this.prefWidth = builder.prefWidth;
        this.minWidth = builder.minWidth;
        this.maxWidth = builder.maxWidth;

        this.height = builder.height;

        this.title = builder.title;
        this.titleWidth = builder.titleWidth;

        this.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);

        this.getStyleClass().add("tableView");

        this.setPrefWidth(prefWidth);
        this.setMinWidth(minWidth);
        this.setMaxWidth(maxWidth);

        this.setPrefHeight(height);

        this.setEditable(false);

        DropShadow ds = new DropShadow();

        ds.setOffsetY(3.0);
        ds.setOffsetX(3.0);
        ds.setColor(Color.DARKGRAY);

        this.setEffect(ds);

        this.withContextMenu = builder.withContextMenu;
        this.menu = builder.menu;

        this.placeHolder = builder.placeHolder;

        if (placeHolder != null)
            this.setPlaceholder(placeHolder);

        // colonnes du tableau
        this.cols = builder.cols;

        if (cols != null) {
            for (final InfoColumnBean col : cols) {
                @SuppressWarnings("rawtypes")
                TableColumn ws_col = null;

                if (col.isColumnWithImage()) {
                    ws_col = new TableColumn<ObservableList<Pair<String, Object>>, Object>(
                            col.getName());

                    ws_col.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList<Pair<String, Object>>, Object>, ObservableValue<Object>>() {
                        @SuppressWarnings("rawtypes")
                        public ObservableValue<Object> call(
                                TableColumn.CellDataFeatures<ObservableList<Pair<String, Object>>, Object> data) {
                            Object value = data.getValue().get(col.getIndex())
                                    .getValue();
                            return (value instanceof ObservableValue) ? (ObservableValue) value
                                    : new ReadOnlyObjectWrapper<>(value);
                        }
                    });
                }

                if (!col.isColumnWithImage()) {
                    ws_col = new TableColumn<ObservableList<Pair<String, Object>>, String>(
                            col.getName());

                    if (!col.isColumnWithDecimalsManagement())
                        ws_col.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList<Pair<String, Object>>, String>, ObservableValue<String>>() {
                            public ObservableValue<String> call(
                                    TableColumn.CellDataFeatures<ObservableList<Pair<String, Object>>, String> data) {
                                return new ReadOnlyObjectWrapper<>(data
                                        .getValue().get(col.getIndex())
                                        .getKey());
                            }
                        });
                    else {
                        ws_col.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList<Pair<String, Object>>, String>, ObservableValue<String>>() {
                            public ObservableValue<String> call(
                                    TableColumn.CellDataFeatures<ObservableList<Pair<String, Object>>, String> data) {
                                // gestion des décimales
                                NumberFormat df = DecimalFormat.getInstance();
                                df.setMaximumFractionDigits(2);
                                df.setMinimumFractionDigits(2);

                                df.setRoundingMode(RoundingMode.HALF_UP);

                                String ret = df.format(
                                        Double.parseDouble(data.getValue()
                                                .get(col.getIndex()).getKey()))
                                        .replace(",", ".");

                                return new ReadOnlyObjectWrapper<>(ret);
                            }
                        });
                    }
                }

                if (col.getId() != null && !col.getId().equals("")) {
                    logger.debug("col_name, id = " + col.getName() + " "
                            + col.getId());
                    ws_col.setId(col.getId());
                }

                ws_col.setPrefWidth(col.getPrefWidth());

                ws_col.setMinWidth(col.getMinWidth());

                ws_col.setMaxWidth(col.getMaxWidth());

                ws_col.getStyleClass().add(col.getStyle());

                ws_col.setResizable(col.isResizable());

                ws_col.setSortable(col.isSortable());

                if (col.getBindPrefWidthWithTable() > 0)
                    ws_col.prefWidthProperty().bind(
                            this.widthProperty().subtract(
                                    col.getBindPrefWidthWithTable()));

                this.getColumns().add(ws_col);
            }

            logger.debug("cols size = " + this.getColumns().size());

            // données
            this.data = builder.data;

            if (data != null) {
                // style lignes
                refresh();

                this.setItems(data);
                logger.debug("data.size = " + data.size());
            } else {
                ObservableList<ObservableList<Pair<String, Object>>> items = FXCollections
                        .observableArrayList();

                this.setItems(items);
            }

            // menu contextuel ?
            final CustomTableView<T> current = this;

            if (withContextMenu) {
                this.addEventHandler(MouseEvent.MOUSE_CLICKED,
                        new EventHandler<MouseEvent>() {
                            @Override
                            public void handle(MouseEvent event) {
                                if (event.getButton().equals(
                                        MouseButton.SECONDARY)
                                        && current.getItems().size() > 0) {
                                    menu.show(current, event.getScreenX(),
                                            event.getScreenY());
                                }
                            }
                        });
            }
        }
    }

    /**
     * @return titre du contrôle
     * 
     * @since 0.0.8
     */
    public String getTitle() {
        return title;
    }

    /**
     * @return longueur titre label
     * 
     * @since 0.0.8
     */
    public int getTitleWidth() {
        return titleWidth;
    }

    /**
     * refresh tableView
     * 
     * @since 0.0.8
     */
    public void refresh() {
        this.setRowFactory(new Callback<TableView<ObservableList<Pair<String, Object>>>, TableRow<ObservableList<Pair<String, Object>>>>() {
            @Override
            public TableRow<ObservableList<Pair<String, Object>>> call(
                    TableView<ObservableList<Pair<String, Object>>> tableView) {
                final TableRow<ObservableList<Pair<String, Object>>> row = new TableRow<ObservableList<Pair<String, Object>>>() {
                    protected void updateItem(
                            ObservableList<Pair<String, Object>> pair,
                            boolean empty) {
                        super.updateItem(pair, empty);

                        int idx = getIndex();

                        if (idx >= 0) {
                            if ((idx % 2) == 0)
                                getStyleClass().add("ligne1");
                            else
                                getStyleClass().add("ligne2");
                        }
                    }
                };

                return row;
            }
        });
    }

    @Override
    public CustomTableView<T> clone() throws CloneNotSupportedException {
        CustomTableView<T> cloneObject = new CustomTableView<T>();

        cloneObject.setItems(super.getItems());

        return cloneObject;
    }

    /**
     * useful for cloning
     * 
     * @since 0.0.8
     */
    public CustomTableView() {
        super();
    }

    /**
     * 
     * Classe : CustomTableViewBuilder
     * 
     * paramètres contrôle
     * 
     * @author fmaupin
     * 
     * @since 0.0.8
     * 
     */
    public static class CustomTableViewBuilder<T> {
        private double prefWidth = 200; // optionnel

        private double minWidth = 200; // optionnel

        private double maxWidth = 200; // optionnel

        private double height = 200; // optionnel

        private List<InfoColumnBean> cols = null; // optionnel

        private ObservableList<ObservableList<Pair<String, Object>>> data = null; // optionnel

        private boolean withContextMenu = false; // optionnel

        private ContextMenu menu = null; // optionnel

        private String title = ""; // obligatoire

        private int titleWidth = 0; // optionnel

        private Label placeHolder = null; // optionnel

        /**
         * @param title
         *            : titre label contrôle
         * 
         * @since 0.0.8
         */
        public CustomTableViewBuilder(String title) {
            this.title = title;
        }

        /**
         * 
         * longueur titre contrôle
         * 
         * @param width
         *            : longueur titre
         * 
         * @since 0.0.8
         */
        public CustomTableViewBuilder<T> titleWidth(int width) {
            this.titleWidth = width;

            return this;
        }

        /**
         * 
         * placeholder
         * 
         * @param value
         *            : message pour placeholder
         * 
         * @since 0.0.8
         */
        public CustomTableViewBuilder<T> setPlaceHolder(String value) {
            this.placeHolder = new Label(value);

            return this;
        }

        /**
         * 
         * largeurs tableau
         * 
         * @param width
         *            : toutes largeurs tableau
         * 
         * @since 0.0.8
         */
        public CustomTableViewBuilder<T> with(double width) {
            this.prefWidth = width;
            this.minWidth = width;
            this.maxWidth = width;

            return this;
        }

        /**
         * 
         * largeur tableau
         * 
         * @param width
         *            : largeur tableau
         * 
         * @since 0.0.8
         */
        public CustomTableViewBuilder<T> prefWith(double width) {
            this.prefWidth = width;

            return this;
        }

        /**
         * 
         * largeur minimale tableau
         * 
         * @param width
         *            : largeur tableau
         * 
         * @since 0.0.8
         */
        public CustomTableViewBuilder<T> minWith(double width) {
            this.minWidth = width;

            return this;
        }

        /**
         * 
         * largeur maximale tableau
         * 
         * @param width
         *            : largeur tableau
         * 
         * @since 0.0.8
         */
        public CustomTableViewBuilder<T> maxWith(double width) {
            this.maxWidth = width;

            return this;
        }

        /**
         * 
         * hauteur tableau
         * 
         * @param height
         *            : hauteur tableau
         * 
         * @since 0.0.8
         */
        public CustomTableViewBuilder<T> height(double height) {
            this.height = height;

            return this;
        }

        /**
         * 
         * ajouter colonne(s) dans tableau
         * 
         * @param infoColumns
         *            : informations sur colonnes (nom, index, largeur, largeur
         *            minimum, largeur maximum, style)
         * 
         * @since 0.0.8
         */
        public CustomTableViewBuilder<T> addColumns(
                List<InfoColumnBean> infoColumns) {
            this.cols = infoColumns;

            return this;
        }

        /**
         * 
         * ajouter données dans tableau
         * 
         * @param data
         *            : données à ajouter
         * 
         * @since 0.0.8
         */
        public CustomTableViewBuilder<T> addDATA(
                ObservableList<ObservableList<Pair<String, Object>>> data) {
            this.data = data;

            return this;
        }

        /**
         * 
         * avec menu contextuel ?
         * 
         * @param menu
         *            : descriptif menu contextuel
         * 
         * @since 0.0.8
         */
        public CustomTableViewBuilder<T> withContextMenu(ContextMenu menu) {
            this.withContextMenu = true;
            this.menu = menu;

            return this;
        }

        /**
         * construire contrôle
         * 
         * @since 0.0.8
         */
        public CustomTableView<T> build() {
            return new CustomTableView<T>(this);
        }
    }
}

我的自定义TableView的初始化(InfoColumns包含列的描述):

mytable = new CustomTableView.CustomTableViewBuilder<ObservableList<Pair<String, Object>>>(
            "")
            .setPlaceHolder(
                    "my message !")
            .addColumns(infoColumns).prefWith(width * 0.4f)
            .minWith(TABLEVIEW_WIDTH).maxWith(width).height(height * 0.75)
            .build();

我的约束力:

mytable.getColumns().get(1).prefWidthProperty().bind(mytable.widthProperty().subtract(385));

不幸的是它不起作用!

如果你有想法......

提前谢谢你

和Fabrice

1 个答案:

答案 0 :(得分:0)

确实有效,请按照以下示例进行操作:

import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class TableViewColumnBind extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        BorderPane borderPane = new BorderPane();
        Scene scene = new Scene(borderPane, 500, 500);
        String cssFile = getClass().getResource("tableviewgridline.css").toExternalForm();
        scene.getStylesheets().add(cssFile);
        stage.setScene(scene);

        TableView<Integer> table = new TableView<>();

        ObservableList<Integer> data = FXCollections.observableArrayList();
        for (int i = 0; i < 20; i++) {
            data.add(i);
        }
        table.setItems(data);

        for (int i = 0; i < 10; i++) {
            TableColumn<Integer,String> column = new TableColumn<>(Integer.toString(i));
            column.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue().toString()));
            table.getColumns().add(column);
        }

        table.getColumns().get(1).prefWidthProperty().bind(table.widthProperty().subtract(400));

        borderPane.setCenter(table);
        stage.show();
    }

    public static void main(String[] args) {
        Application.launch(args);
    }
}