2017-09-19 3 views
1

Bin auf der Suche nach einem TableColumn<CustomObject, String> tableColumn basierend auf einem Feld Wert in CustomObject nur wenn das Kontrollkästchen TableColumn<CustomObject, Boolean> tableColumnTwo aktiviert ist. Ich kann die Textbox innerhalb deaktivieren jedoch nicht sicher, wie der Zustand der Checkbox innerhalb updateItem zu überprüfen Im Folgenden finden Sie die entsprechenden Code-Schnipsel, wäre sehr dankbar, wenn jemand Licht auf dieseJavaFX Disable TableColumn basierend auf Checkbox-Status

@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(""); 
             } 
            } 
           } 
          }; 
         } 

        }); 
+0

https://stackoverflow.com/help/how-to-ask oder mit anderen Worten: Bitte geben Sie ein ausführbares Beispiel an, das Ihnen zeigt, was Sie suchen und wie Sie Ihr Ziel nicht erreichen können :) – kleopatra

Antwort

1

Sie können einen Listener auf das Kontrollkästchen hinzufügen, die, wenn sie überprüft die Tabelle Refresh verursachen.

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)); 
       } 
      } 
     } 
    }); 

Ihre cellFactory würde gleich bleiben und würde aufgerufen werden, wenn ein Kontrollkästchen aktiviert ist/nicht aktiviert.

1

Normalerweise vergießen kann, erwarten wir Zellen sein aktualisiert, wenn sie über eine Änderung der zugrunde liegenden Daten benachrichtigt werden. Um sicherzustellen, dass eine Benachrichtigung durch die Daten über die Änderung einer Eigenschaft eines Elements ausgelöst wird, müssen wir eine Liste mit einem Extraktor auf die Eigenschaften, die wir interessiert sind, so etwas wie:

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

, die mit an Stelle der Liste löscht eine Listenänderung der Typaktualisierung, wenn sich die vordefinierte Eigenschaft ändert.

Leider ist das nicht genug aufgrund einer bug in fx: Zellen werden nicht aktualisiert, wenn Sie eine ListChange des Typs Update von den zugrunde liegenden Elementen erhalten. Ein schmutziger Weg herum (lesen Sie: nicht verwenden, sobald der Fehler behoben ist, es ist Notfall-API!) Ist ein Listener auf die Elemente zu installieren und table.refresh() aufrufen, wenn ein Update erhalten.

Ein Beispiel:

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()); 
} 
Verwandte Themen