2016-04-14 11 views
0

Wie bekomme ich den Namen der Spalte eines Textfelds in einer javaFX-Tabelle? Ich brauche dies, um den Wert der Zellen nur in der Spalte "text2" zu überprüfen. Ich habe es mit textfield.parent() versucht, aber ich habe kein nützliches Ergebnis bekommen. Hier ist mein Code:javafx: Erhalte den Namen der Spalte

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

    } 

} 

Antwort

1

Es gibt wahrscheinlich (Weg) bessere Möglichkeiten, dies zu organisieren, aber wahrscheinlich die sauberste Lösung ist nur einen boolean validate Parameter an den Konstruktor Ihrer Zelle Implementierung zu definieren. (Sie wollen wirklich nicht, dass die Logik "wenn der Titel der Spalte gleich einem bestimmten Text ist, dann validiere". Sie würden völlig verarscht sein, wenn Ihr Chef in das Büro kam und Sie bat, die Anwendung zu internationalisieren, oder sogar ändern Sie einfach den Titel der Spalte, zum Beispiel)

eine ganze innere Klasse nur mit dem Rückruf zu implementieren völlig überflüssig scheint, aber halten, dass Sie den Parameter durch sie hindurchtreten müsste.

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

        } 

       }); 
      } 

     } 

     // ... 

} 

Dann tun Sie natürlich nur

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

(Um Ihre Frage richtig zu beantworten, können Sie den Text der Spalte innerhalb der Zelle, an die er angeschlossen ist, mit getTableColumn().getText() abrufen, aber wie ich bereits erwähnt habe, wird der Code durch die Logik auf dem in einer Spaltenüberschrift angezeigten Wert basieren völlig unhaltbar.)

Und ich denke, für die Vollständigkeit, sollte ich auch erwähnen, dass Ihre TextFieldCellFactory Klasse aussieht, als ob es wirklich keinen Zweck dient. Ich würde es vollständig entfernen und nur die TextFieldCell Klasse haben, und tun

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