2017-09-19 2 views
1

Je souhaite désactiver un TableColumn<CustomObject, String> tableColumn en fonction d'une valeur de zone dans la zone CustomObject uniquement lorsque la case TableColumn<CustomObject, Boolean> tableColumnTwo est cochée. Je peux désactiver la zone de texte à l'intérieur mais ne savez pas comment vérifier l'état de case à cocher dans updateItem Voici l'extrait de code correspondant, apprécierait si quelqu'un peut faire la lumière sur cetteJavaFX Désactiver TableColumn en fonction de l'état de la case à cocher

@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 – kleopatra

Répondre

1

Vous pouvez ajouter un écouteur sur la case à cocher, qui lorsqu'elle est cochée provoque la mise à jour de la table.

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

Votre cellFactory demeurerait le même et serait déclenchée lorsqu'un case est cochée/décochée. Ou en d'autres termes: veuillez fournir un exemple exécutable qui montre ce que vous cherchez et comment vous ne parvenez pas à atteindre votre objectif :)

1

Habituellement, nous nous attendons à des cellules étant mis à jour chaque fois qu'ils sont informés d'un changement dans les données sous-jacentes. Pour s'assurer qu'une notification est tirée par les données sur la modification d'une propriété d'un élément, nous avons besoin d'une liste avec un extracteur sur les propriétés qui nous intéressent, quelque chose comme:

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

Cela en place la liste déclenche un changement de liste de type mise à jour chaque fois que la propriété pretified change.

Malheureusement, ce n'est pas suffisant en raison d'un bug in fx: les cellules ne sont pas mises à jour lors de la réception d'une mise à jour listChange de type à partir des éléments sous-jacents. Un moyen détourné (lire: ne pas utiliser une fois le bug corrigé, c'est l'utilisation d'une API d'urgence!) Consiste à installer un écouteur sur les éléments et à appeler le table.refresh() lors de la réception d'une mise à jour.

Un exemple:

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