2016-04-14 1 views
0

Comment obtenir le nom de la colonne d'un champ de texte dans une table javaFX? J'ai besoin de ceci pour vérifier la valeur des cellules seulement dans la colonne "text2". Je l'ai essayé avec textfield.parent() mais je n'ai pas obtenu un résultat utile. Voici mon code:javafx: récupère le nom de la colonne

import java.util.ArrayList; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 
import javafx.beans.value.ChangeListener; 
import javafx.beans.value.ObservableValue; 
import javafx.scene.control.ContentDisplay; 
import javafx.scene.control.TableCell; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TextArea; 
import javafx.util.Callback; 

import javafx.application.Application; 
import static javafx.application.Application.launch; 
import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.geometry.Insets; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.Label; 
import javafx.scene.control.TableView; 
import javafx.scene.control.cell.PropertyValueFactory; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.HBox; 
import javafx.stage.Stage; 


/*interface inside_table 
{ 
    public String get_column_name 
}*/ 

public class Supermain extends Application { 

    @Override 
    public void start(Stage primaryStage) { 

     ArrayList myindizes=new ArrayList(); 



     final TableView<myTextRow> table = new TableView<>(); 
     table.setEditable(true); 
     table.setStyle("-fx-text-wrap: true;"); 

     //Table columns 
     TableColumn<myTextRow, String> clmID = new TableColumn<>("ID"); 
     clmID.setMinWidth(160); 
     clmID.setCellValueFactory(new PropertyValueFactory<>("ID")); 

     TableColumn<myTextRow, String> clmtext = new TableColumn<>("Text"); 
     clmtext.setMinWidth(160); 
     clmtext.setCellValueFactory(new PropertyValueFactory<>("text")); 
     clmtext.setCellFactory(new TextFieldCellFactory()); 

     TableColumn<myTextRow, String> clmtext2 = new TableColumn<>("Text2"); 
     clmtext2.setMinWidth(160); 
     clmtext2.setCellValueFactory(new PropertyValueFactory<>("text2")); 
     clmtext2.setCellFactory(new TextFieldCellFactory()); 

     //Add data 
     final ObservableList<myTextRow> data = FXCollections.observableArrayList(
       new myTextRow(5, "Lorem","bla"), 
       new myTextRow(2, "Ipsum","bla") 
     ); 

     table.getColumns().addAll(clmID, clmtext,clmtext2); 
     table.setItems(data); 

     HBox hBox = new HBox(); 
     hBox.setSpacing(5.0); 
     hBox.setPadding(new Insets(5, 5, 5, 5)); 

     Button btn = new Button(); 
     btn.setText("Get Data"); 
     btn.setOnAction(new EventHandler<ActionEvent>() { 

      @Override 
      public void handle(ActionEvent event) { 
       for (myTextRow data1 : data) { 
        System.out.println("data:" + data1.getText2()); 
       } 
      } 
     }); 

     hBox.getChildren().add(btn); 

     BorderPane pane = new BorderPane(); 
     pane.setTop(hBox); 
     pane.setCenter(table); 
     primaryStage.setScene(new Scene(pane, 640, 480)); 
     primaryStage.show(); 


    } 

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String[] args) { 
     launch(args); 
    } 


    public static class TextFieldCellFactory 
      implements Callback<TableColumn<myTextRow, String>, TableCell<myTextRow, String>> { 

     @Override 
     public TableCell<myTextRow, String> call(TableColumn<myTextRow, String> param) { 
      TextFieldCell textFieldCell = new TextFieldCell(); 
      return textFieldCell; 

     } 

     public static class TextFieldCell extends TableCell<myTextRow, String> { 

      private TextArea textField; 
      private StringProperty boundToCurrently = null; 
      private String last_text; 


      public TextFieldCell() { 

       textField = new TextArea(); 
       textField.setWrapText(true); 
       textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2); 
       last_text=""; 



       this.setGraphic(textField); 

       textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> { 
//only if textfield is in the text2 column 
        if(isNowFocused){last_text=textField.getText(); System.out.println("NOW focus "+last_text);} 
        if (! isNowFocused && ! isValid(textField.getText())) { 
         textField.setText(last_text); 
         textField.selectAll(); 
         System.out.println("blur"); 

        } 

       }); 

      } 

      @Override 
      protected void updateItem(String item, boolean empty) { 
       super.updateItem(item, empty); 
       if (!empty) { 
        // Show the Text Field 
        this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY); 


        // myindizes.add(getIndex()); 

        // Retrieve the actual String Property that should be bound to the TextField 
        // If the TextField is currently bound to a different StringProperty 
        // Unbind the old property and rebind to the new one 
        ObservableValue<String> ov = getTableColumn().getCellObservableValue(getIndex()); 
        SimpleStringProperty sp = (SimpleStringProperty) ov; 

        if (this.boundToCurrently == null) { 
         this.boundToCurrently = sp; 
         this.textField.textProperty().bindBidirectional(sp); 
        } else if (this.boundToCurrently != sp) { 
         this.textField.textProperty().unbindBidirectional(this.boundToCurrently); 
         this.boundToCurrently = sp; 
         this.textField.textProperty().bindBidirectional(this.boundToCurrently); 
        } 

        double height = real_lines_height(textField.getText(), this.getWidth(), 30, 22); 
        textField.setPrefHeight(height); 
        textField.setMaxHeight(height); 

        textField.setMaxHeight(Double.MAX_VALUE); 
        // if height bigger than the biggest height in the row 
        //-> change all heights of the row(textfields()typeof textarea) to this height 
        // else leave the height as it is 


        //System.out.println("item=" + item + " ObservableValue<String>=" + ov.getValue()); 
        //this.textField.setText(item); // No longer need this!!! 
       } else { 
        this.setContentDisplay(ContentDisplay.TEXT_ONLY); 
       } 
      }//update 

      private boolean isValid(String s){ 

       if(s.length()<7){return true;} 
       return false; 


      } 

     } 

    } 

    public class myTextRow { 

     private final SimpleIntegerProperty ID; 

     private final SimpleStringProperty text; 
     private final SimpleStringProperty text2; 

     public myTextRow(int ID, String text,String text2) { 

      this.ID = new SimpleIntegerProperty(ID); 
      this.text = new SimpleStringProperty(text); 
      this.text2 = new SimpleStringProperty(text2); 


     } 


     //setter 
     public void setID(int id) { 
      this.ID.set(id); 
     } 

     public void setText(String text) { 
      this.text.set(text); 
     } 

     public void setText2(String text) {   
      this.text2.set(text);   
     } 

     //getter 
     public int getID() { 
      return ID.get(); 
     } 

     public String getText() { 
      return text.get(); 
     } 

     public String getText2() { 
      return text2.get(); 
     } 

     //properties 
     public StringProperty textProperty() { 
     return text; 

     } 

     public StringProperty text2Property() { 
     return text2; 

     } 

    public IntegerProperty IDProperty() { 
     return ID; 
    } 

    } 

    private static double real_lines_height(String s, double width, double heightCorrector, double widthCorrector) { 
     HBox h = new HBox(); 
     Label l = new Label("Text"); 
     h.getChildren().add(l); 
     Scene sc = new Scene(h); 
     l.applyCss(); 
     double line_height = l.prefHeight(-1); 

     int new_lines = s.replaceAll("[^\r\n|\r|\n]", "").length(); 
     // System.out.println("new lines= "+new_lines); 
     String[] lines = s.split("\r\n|\r|\n"); 
     // System.out.println("line count func= "+ lines.length); 
     int count = 0; 
     //double rest=0; 
     for (int i = 0; i < lines.length; i++) { 
      double text_width = get_text_width(lines[i]); 
      double plus_lines = Math.ceil(text_width/(width - widthCorrector)); 
      if (plus_lines > 1) { 
       count += plus_lines; 
       //rest+= (text_width/(width-widthCorrector)) - plus_lines; 
      } else { 
       count += 1; 
      } 

     } 
     //count+=(int) Math.ceil(rest); 
     count += new_lines - lines.length; 

     return count * line_height + heightCorrector; 
    } 

    private static double get_text_width(String s) { 
     HBox h = new HBox(); 
     Label l = new Label(s); 
     l.setWrapText(false); 
     h.getChildren().add(l); 
     Scene sc = new Scene(h); 
     l.applyCss(); 
     // System.out.println("dubbyloop.FXMLDocumentController.get_text_width(): "+l.prefWidth(-1)); 
     return l.prefWidth(-1); 

    } 

} 

Répondre

1

Il y a probablement (aller) de meilleures façons d'organiser, mais sans doute le plus propre solution est juste pour définir un paramètre boolean validate au constructeur de votre implémentation cellulaire. (Vous ne voulez vraiment pas que la logique soit "si le titre de la colonne est égal à un texte spécifique, alors validez." Vous seriez complètement foutu quand votre patron est entré au bureau et vous a demandé d'internationaliser l'application, ou même simplement changer le titre de la colonne, par exemple)

utilisant une classe interne entière juste pour mettre en œuvre le rappel semble complètement redondant, mais en gardant ce que vous devez passer le paramètre à travers elle.

public static class TextFieldCellFactory 
     implements Callback<TableColumn<myTextRow, String>, TableCell<myTextRow, String>> { 

    private final boolean validate ; 

    public TextFieldCellFactory(boolean validate) { 
     this.validate = validate ; 
    } 

    @Override 
    public TableCell<myTextRow, String> call(TableColumn<myTextRow, String> param) { 
     TextFieldCell textFieldCell = new TextFieldCell(validate); 
     return textFieldCell; 

    } 

    public static class TextFieldCell extends TableCell<myTextRow, String> { 

     private TextArea textField; 
     private StringProperty boundToCurrently = null; 
     private String last_text; 

     public TextFieldCell(boolean validate) { 

      textField = new TextArea(); 
      textField.setWrapText(true); 
      textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2); 
      last_text=""; 



      this.setGraphic(textField); 

      if (validate) { 
       textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> { 
//only if textfield is in the text2 column 
        if(isNowFocused){last_text=textField.getText(); System.out.println("NOW focus "+last_text);} 
        if (! isNowFocused && ! isValid(textField.getText())) { 
         textField.setText(last_text); 
         textField.selectAll(); 
         System.out.println("blur"); 

        } 

       }); 
      } 

     } 

     // ... 

} 

Alors bien sûr vous venez

TableColumn<myTextRow, String> clmtext = new TableColumn<>("Text"); 
clmtext.setMinWidth(160); 
clmtext.setCellValueFactory(new PropertyValueFactory<>("text")); 
clmtext.setCellFactory(new TextFieldCellFactory(false)); 

TableColumn<myTextRow, String> clmtext2 = new TableColumn<>("Text2"); 
clmtext2.setMinWidth(160); 
clmtext2.setCellValueFactory(new PropertyValueFactory<>("text2")); 
clmtext2.setCellFactory(new TextFieldCellFactory(true)); 

(Pour répondre correctement à votre question, vous pouvez obtenir le texte de la colonne à partir de la cellule à laquelle il est attaché avec getTableColumn().getText(), mais comme je l'ai souligné, baser la logique sur la valeur affichée dans un en-tête de colonne fera votre code complètement insaisissable.)

Et j'imagine que pour être complet, je devrais aussi mentionner que votre classe TextFieldCellFactory a l'air de ne servir à rien. Je voudrais l'enlever entièrement et juste avoir la classe TextFieldCell, et faire

TableColumn<myTextRow, String> clmtext = new TableColumn<>("Text"); 
clmtext.setMinWidth(160); 
clmtext.setCellValueFactory(new PropertyValueFactory<>("text")); 
clmtext.setCellFactory(c -> new TextFieldCell(false)); 

TableColumn<myTextRow, String> clmtext2 = new TableColumn<>("Text2"); 
clmtext2.setMinWidth(160); 
clmtext2.setCellValueFactory(new PropertyValueFactory<>("text2")); 
clmtext2.setCellFactory(c -> new TextFieldCell(true));