簡體   English   中英

JavaFX根據復選框狀態禁用TableColumn

[英]JavaFX Disable TableColumn based on checkbox state

在找到禁用TableColumn<CustomObject, String> tableColumn基於在字段值CustomObject只有當TableColumn<CustomObject, Boolean> tableColumnTwo復選框被選中。 我可以在public void updateItem(String s, boolean empty)中禁用文本框但是不確定如何檢查updateItem里面的復選框狀態下面是相關的代碼片段,如果有人能夠闡明這一點,我將非常感激

@FXML 
private TableColumn<CustomObject, Boolean> tableColumnTwo;
@FXML 
private TableColumn<CustomObject, String> tableColumn;

tableColumn.setCellFactory(
                     new Callback<TableColumn<CustomObject, String>, TableCell<CustomObject, String>>() {

                         @Override
                         public TableCell<CustomObject, String> call(TableColumn<CustomObject, String> paramTableColumn) {
                             return new TextFieldTableCell<CustomObject, String>(new DefaultStringConverter()) {
                                 @Override
                                 public void updateItem(String s, boolean empty) {
                                     super.updateItem(s, empty);
                                     TableRow<CustomObject> currentRow = getTableRow();
                                     if(currentRow.getItem() != null && !empty) {
                                         if (currentRow.getItem().getPetrified() == false) { // Need to check if checkbox is checked or not
                                             setDisable(true);
                                             setEditable(false);
                                             this.setStyle("-fx-background-color: red");
                                         } else {
                                             setDisable(false);
                                             setEditable(true);
                                                                                             setStyle("");
                                         }
                                     }
                                 }
                             };
                         }

                     });

您可以在復選框上添加一個監聽器,選中此復選框將導致表刷新。

data = FXCollections.observableArrayList(new Callback<CustomObject, Observable[]>() {

            @Override
            public Observable[] call(CustomObject param) {
                return new Observable[]{param.petrifiedProperty()};
            }
    });


data.addListener(new ListChangeListener<CustomObject>() {

        @Override
        public void onChanged(ListChangeListener.Change<? extends CustomObject> c) {
            while (c.next()) {
                if (c.wasUpdated()) {
                    tableView.setItems(null); 
                    tableView.layout(); 
                    tableView.setItems(FXCollections.observableList(data)); 
                }
            }
        }
    });

您的cellFactory將保持不變,並在選中/取消選中復選框時調用它。

通常,我們希望每當有關基礎數據發生變化的通知時,都會更新單元格。 為了確保更改項目屬性的數據觸發通知,我們需要一個包含我們感興趣的屬性的提取器的列表,例如:

 ObservableList<CustomObject> data = FXCollections.observableArrayList(
      c ->  new Observable[] {c.petrifiedProperty()}
 );

有了這個,只要知情屬性發生變化,列表就會觸發類型更新的列表更改。

不幸的是,由於fx中錯誤 ,這還不夠:當從基礎項接收類型更新的listChange時,單元格不會更新。 一個骯臟的方式(閱讀:一旦修復bug就不要使用,它使用緊急api!)是在項目上安裝一個監聽器,並在接收更新時調用table.refresh()

一個例子:

import java.util.logging.Logger;

//import de.swingempire.fx.util.FXUtils;
import javafx.application.Application;
import javafx.beans.Observable;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.converter.DefaultStringConverter;

/**
 * CheckBoxTableCell: update editable state of one column based of  
 * the boolean in another column
 * https://stackoverflow.com/q/46290417/203657
 * 
 * Bug in skins: cell not updated on listChange.wasUpdated
 * 
 * reported as
 * https://bugs.openjdk.java.net/browse/JDK-8187665
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public class TableViewUpdateBug extends Application {


    /**
     * TableCell that updates state based on another value in the row.
     */
    public static class DisableTextFieldTableCel extends TextFieldTableCell {

        public DisableTextFieldTableCel() {
            super(new DefaultStringConverter());
        }

        /**
         * Just to see whether or not this is called on update notification
         * from the items (it's not)
         */
        @Override
        public void updateIndex(int index) {
            super.updateIndex(index);
//            LOG.info("called? " + index);
        }

        /**
         * Implemented to change background based on 
         * visible property of row item.
         */
        @Override
        public void updateItem(Object item, boolean empty) {
            super.updateItem(item, empty);
            TableRow<TableColumn> currentRow = getTableRow();
            boolean editable = false;
            if (!empty && currentRow != null) {
                TableColumn column = currentRow.getItem();
                if (column != null) {
                    editable = column.isVisible();
                }
            }
            if (!empty) {
                setDisable(!editable);
                setEditable(editable);
                if (editable) {
                    this.setStyle("-fx-background-color: red");

                } else {
                    this.setStyle("-fx-background-color: green");
                }
            } else {
                setStyle("-fx-background-color: null");
            }
        }

    }

    @Override
    public void start(Stage primaryStage) {
        // data: list of tableColumns with extractor on visible property
        ObservableList<TableColumn> data = FXCollections.observableArrayList(
                c ->  new Observable[] {c.visibleProperty()});

        data.addAll(new TableColumn("first"), new TableColumn("second"));

        TableView<TableColumn> table = new TableView<>(data);
        table.setEditable(true);

        // hack-around: call refresh
        data.addListener((ListChangeListener) c -> {
            boolean wasUpdated = false;
            boolean otherChange = false;
            while(c.next()) {
                if (c.wasUpdated()) {
                    wasUpdated = true;
                } else {
                    otherChange = true;
                }

            }
            if (wasUpdated && !otherChange) {
                table.refresh();
            }
            //FXUtils.prettyPrint(c);
        });
        TableColumn<TableColumn, String> text = new TableColumn<>("Text");
        text.setCellFactory(c -> new DisableTextFieldTableCel()); 
        text.setCellValueFactory(new PropertyValueFactory<>("text"));

        TableColumn<TableColumn, Boolean> visible = new TableColumn<>("Visible");
        visible.setCellValueFactory(new PropertyValueFactory<>("visible"));
        visible.setCellFactory(CheckBoxTableCell.forTableColumn(visible));

        table.getColumns().addAll(text, visible);

        BorderPane root = new BorderPane(table);
        Scene scene = new Scene(root, 300, 150);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

    @SuppressWarnings("unused")
    private static final Logger LOG = Logger
            .getLogger(TableViewUpdateBug.class.getName());
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM