2016-04-14 116 views
0

如何獲取javaFX表內的textfield列的名稱? 我需要這個來檢查只在「text2」列中的單元格的值。我用textfield.parent()試過了,但沒有得到有用的結果。 這裏是我的代碼:javafx:獲取列的名稱

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

    } 

} 

回答

1

有可能(的方式)更好的方式來組織這一點,但可能是最清晰的解決方法是隻定義boolean validate參數到您的實現的構造函數。 (你真的不希望邏輯是「如果列的標題等於一些特定的文本,然後驗證」。當你的老闆進入辦公室並要求你將應用程序國際化時,你會被徹底搞砸,甚至只是更改列的標題,例如)

使用整個內部類只是爲了實現回調似乎完全是多餘的,但保留,你將不得不通過它來傳遞參數:

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

        } 

       }); 
      } 

     } 

     // ... 

} 

那麼當然你只是做

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

(要正確回答您的問題,您可以從與getTableColumn().getText()相連的單元格中獲取列的文本,但正如我所指出的,實際上將邏輯基於顯示在列標題中的值將使您的代碼完全無法維護。)

我想完整性,我還應該提到你的TextFieldCellFactory類看起來並不真正起任何作用。我會完全刪除它,只有TextFieldCell類,並做

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