2013-10-02 2 views
1

У меня есть таблицы с редактируемыми полями firstName, lastName и fullName. Я создаю cellFactory и Колонна, как этотJavafx Editable Table cell

public class SampleFX1 extends Application { 
private TableView table = new TableView(); 
private final ObservableList<Person> data = 
     FXCollections.observableArrayList(new Person("balu", "Smith","1"), new Person("Isabella", "john","1"), 
     new Person("Ethan", "Williams","1"), new Person("Emma", "Jones","1"), new Person("Michael", "Brown","1")); 

public static void main(String[] args) { 
    launch(args); 
} 

@Override 
public void start(Stage stage) { 
    Scene scene = new Scene(new Group()); 

    TableColumn firstNameCol = createSimpleFirstNameColumn(); 
    TableColumn lastNameCol = createLastNameColumn(); 
    TableColumn fullNameCol = createfullNameColumn(); 
    table.setItems(data); 
    table.getColumns().addAll(firstNameCol, lastNameCol,fullNameCol); 
    table.setEditable(true); 

    ((Group) scene.getRoot()).getChildren().addAll(table); 
    stage.setScene(scene); 
    stage.show(); 
} 

private TableColumn createSimpleFirstNameColumn() { 
    TableColumn firstNameCol = new TableColumn("First Name"); 
    firstNameCol.setMinWidth(100); 
    firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 
    firstNameCol.setCellFactory(TextFieldTableCell.forTableColumn()); 
    firstNameCol.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Person, String>>() { 
     @Override 
     public void handle(TableColumn.CellEditEvent<Person, String> t) { 
      t.getRowValue().setFirstName(t.getNewValue()); 
     } 
    }); 

    return firstNameCol; 
} 

private TableColumn createLastNameColumn() { 
    Callback<TableColumn, TableCell> editableFactory = new Callback<TableColumn, TableCell>() { 
     @Override 
     public TableCell call(TableColumn p) { 
      return new EditingCell(); 
     } 
    }; 

    TableColumn lastNameCol = new TableColumn("Last Name"); 
    lastNameCol.setMinWidth(100); 
    lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); 
    lastNameCol.setCellFactory(editableFactory); 
    lastNameCol.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Person, String>>() { 
     @Override 
     public void handle(TableColumn.CellEditEvent<Person, String> t) { 
      System.out.println("Commiting last name change. Previous: " + t.getOldValue() + " New: " + t.getNewValue()); 
      t.getRowValue().setLastName(t.getNewValue()); 
     } 
    }); 

    return lastNameCol; 
} 

private TableColumn createfullNameColumn() { 
    TableColumn firstNameCol = new TableColumn("full Name"); 
    firstNameCol.setMinWidth(100); 
    firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("fullName")); 
    firstNameCol.setCellFactory(TextFieldTableCell.forTableColumn()); 
    firstNameCol.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Person, String>>() { 
     @Override 
     public void handle(TableColumn.CellEditEvent<Person, String> t) { 
      t.getRowValue().setfullName(t.getNewValue()); 
     } 
    }); 

    return firstNameCol; 

} 
} 

редактирования Cell:

public class EditingCell extends TableCell<Person, String> { 
private TextField textField; 

public EditingCell() { 
} 

@Override 
public void startEdit() { 
    super.startEdit(); 

    if(textField == null) { 
     createTextField(); 
    } 
    setText(null); 
    setGraphic(textField); 
    textField.selectAll(); 
} 

@Override 
public void cancelEdit() { 
    super.cancelEdit(); 
    setText((String) getItem()); 
    setGraphic(null); 
} 

@Override 
public void updateItem(String item, boolean empty) { 
    super.updateItem(item, empty); 
    if (empty) { 
     setText(null); 
     setGraphic(null); 
    } else { 
     if (isEditing()) { 
      if (textField != null) { 
       textField.setText(getString()); 
      } 
      setText(null); 
      setGraphic(textField); 
     } else { 
      setText(getString()); 
      setGraphic(null); 
     } 
    } 
} 

private void createTextField() { 
    textField = new TextField(getString()); 
    textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2); 
    textField.focusedProperty().addListener(new ChangeListener<Boolean>() { 
     @Override 
     public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2) { 
      if (!arg2) { commitEdit(textField.getText()); } 
     } 
    }); 

    textField.setOnKeyReleased(new EventHandler<KeyEvent>() { 
     @Override 
     public void handle(KeyEvent t) { 
      if (t.getCode() == KeyCode.ENTER) { 
       String value = textField.getText(); 
       if (value != null) { commitEdit(value); } else { commitEdit(null); } 
      } else if (t.getCode() == KeyCode.ESCAPE) { 
       cancelEdit(); 
      } 
     } 
    }); 
} 

private String getString() { 
    return getItem() == null ? "" : getItem().toString(); 
} 
} 

Person Класс:

import javafx.beans.property.SimpleStringProperty; 

public class Person { 
private SimpleStringProperty firstName; 
private SimpleStringProperty lastName; 
private SimpleStringProperty fullName; 



public Person(String firstName, String lastName ,String fullName) { 

    this.firstName = new SimpleStringProperty(firstName); 
    this.lastName = new SimpleStringProperty(lastName); 
    this.fullName=new SimpleStringProperty(fullName); 


} 

public String getFirstName() { return firstName.get(); } 
public void setFirstName(String firstName) { this.firstName.set(firstName); } 
public SimpleStringProperty firstNameProperty() { return firstName; } 

public String getLastName() { return lastName.get(); } 
public void setLastName(String lastName) { this.lastName.set(lastName); } 
public SimpleStringProperty lastNameProperty() { return lastName; } 

public String getfullName() { return fullName.get(); } 
public void setfullName(String lastName) { this.fullName.set(lastName); } 
public SimpleStringProperty fullNameProperty() { return fullName; } 

} 

Вопрос: Как обновить FULLNAME столбец при обновлении ПгвЬЫате Колонка или Lastname Column (редактируемые ячейки) без вставки строки?

ответ

3

Используйте привязку для получения полного имени от имени и фамилии.

fullName.bind(Bindings.concat(this.firstName, " ", this.lastName)); 

Person.java

import javafx.beans.binding.Bindings; 
import javafx.beans.property.ReadOnlyStringProperty; 
import javafx.beans.property.ReadOnlyStringWrapper; 
import javafx.beans.property.SimpleStringProperty; 

public class Person { 
    private SimpleStringProperty firstName; 
    private SimpleStringProperty lastName; 
    private ReadOnlyStringWrapper fullName = new ReadOnlyStringWrapper(); 

    public Person(String firstName, String lastName) { 
     this.firstName = new SimpleStringProperty(firstName); 
     this.lastName = new SimpleStringProperty(lastName); 

     fullName.bind(Bindings.concat(this.firstName, " ", this.lastName)); 
    } 

    public String getFirstName() { 
     return firstName.get(); 
    } 

    public void setFirstName(String firstName) { 
     this.firstName.set(firstName); 
    } 

    public SimpleStringProperty firstNameProperty() { 
     return firstName; 
    } 

    public String getLastName() { 
     return lastName.get(); 
    } 

    public void setLastName(String lastName) { 
     this.lastName.set(lastName); 
    } 

    public SimpleStringProperty lastNameProperty() { 
     return lastName; 
    } 

    public String getFullName() { 
     return fullName.get(); 
    } 

    public ReadOnlyStringProperty fullNameProperty() { 
     return fullName.getReadOnlyProperty(); 
    } 
} 

Переопределение функции вашего createfullNameColumn(). Теперь, когда fullName, что это производное значение от конкатенации firstName и lastName, нет необходимости разрешать пользователю явно редактировать его.

private TableColumn createfullNameColumn() { 
    TableColumn fullNameCol = new TableColumn("Full Name"); 
    fullNameCol.setMinWidth(100); 
    fullNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("fullName")); 

    return fullNameCol; 
} 

SampleFX1.java

Код Применение:

import javafx.application.Application; 
import javafx.collections.*; 
import javafx.event.EventHandler; 
import javafx.scene.*; 
import javafx.scene.control.*; 
import javafx.scene.control.cell.*; 
import javafx.stage.Stage; 
import javafx.util.Callback; 

public class SampleFX1 extends Application { 
    private TableView table = new TableView(); 
    private final ObservableList<Person> data = 
      FXCollections.observableArrayList(
        new Person("balu", "Smith"), 
        new Person("Isabella", "john"), 
        new Person("Ethan", "Williams"), 
        new Person("Emma", "Jones"), 
        new Person("Michael", "Brown") 
      ); 

    public static void main(String[] args) { 
     launch(args); 
    } 

    @Override 
    public void start(Stage stage) { 
     Scene scene = new Scene(new Group()); 

     TableColumn firstNameCol = createSimpleFirstNameColumn(); 
     TableColumn lastNameCol = createLastNameColumn(); 
     TableColumn fullNameCol = createFullNameColumn(); 
     table.setItems(data); 
     table.getColumns().addAll(firstNameCol, lastNameCol, fullNameCol); 
     table.setEditable(true); 

     ((Group) scene.getRoot()).getChildren().addAll(table); 
     stage.setScene(scene); 
     stage.show(); 
    } 

    private TableColumn createSimpleFirstNameColumn() { 
     TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name"); 
     firstNameCol.setMinWidth(100); 
     firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 
     firstNameCol.setCellFactory(TextFieldTableCell.forTableColumn()); 
     firstNameCol.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Person, String>>() { 
      @Override 
      public void handle(TableColumn.CellEditEvent<Person, String> t) { 
       t.getRowValue().setFirstName(t.getNewValue()); 
      } 
     }); 

     return firstNameCol; 
    } 

    private TableColumn createLastNameColumn() { 
     Callback<TableColumn, TableCell> editableFactory = new Callback<TableColumn, TableCell>() { 
      @Override 
      public TableCell call(TableColumn p) { 
       return new EditingCell(); 
      } 
     }; 

     TableColumn lastNameCol = new TableColumn("Last Name"); 
     lastNameCol.setMinWidth(100); 
     lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); 
     lastNameCol.setCellFactory(editableFactory); 
     lastNameCol.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Person, String>>() { 
      @Override 
      public void handle(TableColumn.CellEditEvent<Person, String> t) { 
       System.out.println("Commiting last name change. Previous: " + t.getOldValue() + " New: " + t.getNewValue()); 
       t.getRowValue().setLastName(t.getNewValue()); 
      } 
     }); 

     return lastNameCol; 
    } 

    private TableColumn createFullNameColumn() { 
     TableColumn fullNameCol = new TableColumn("Full Name"); 
     fullNameCol.setMinWidth(100); 
     fullNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("fullName")); 

     return fullNameCol; 
    } 
} 

EditingCell.java

(без изменений от вопроса)


Update, чтобы ответить на дополнительные вопросы пользователей на примере код

Я был в состоянии работать createSimpleFirstNameColumn(), хотя есть много предупреждений от затмения, например: TableColumn является исходным типом. Ссылки на общий тип TableColumn следует параметризовать.

Исходный код был адаптирован из стандартного JavaFX TableView sample code, который в то время был не лучший пример работы с Generics. Спецификация общего типа в Java не является обязательной, но если вы смешиваете использование API, который имеет общие данные, но не предоставляет информацию об общем типе в использовании API, компилятор выдаст предупреждения, такие как выше. В общем случае предупреждения могут быть проигнорированы или, если хотите, хотя вы получите более удобный тип вывода и проверку типа времени компиляции, если вы явно указываете информацию о типе.

Вместо того, чтобы просто сказать:

TableColumn firstNameCol = new TableColumn("First Name"); 

Предупреждения могут быть устранены с помощью информации в явном виде с указанием типа, например, как показано ниже:

TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name"); 

Я обновил пример кода выше, чтобы использовать эти обозначения в createSimpleFirstNameColumn() функция.

Обратите внимание на приведенный выше код использует Java 7 diamond notation, поэтому минимальный уровень языка компиляции программы должен быть установлен по крайней мере Java 7.

Однако в createLastNameColumn() линии с возвратной новой EditingCell() , дает мне ошибку, что EditingCell не может быть разрешен для типа.

Я не получаю эту ошибку. Вероятно, вы не включили класс EditingCell, определенный в исходном вопросе в вашем проекте.

+0

После обновления этого приложения сделать исключение, как это: исключение в конструкторе Применение: причиненном: java.lang.RuntimeException: Невозможно построить экземпляр приложения: класс samplefx1.SampleFX1 Вызванный: java.lang.reflect.InvocationTargetException Вызвано: java.lang.NullPointerException \t на samplefx1.Person. (Person.java:22) –

+0

Извините, был сонлив, когда набрал оригинальный ответ - обновленный ответ с образцовой версией, которая будет компилироваться и работать (базовые концепции такие же, как и раньше). – jewelsea

+0

Спасибо jewelsea .................. –

0

Я не могу оставить комментарий, но в ответ на этот вопрос: пересмотренным

я смог запустить createSimpleFirstNameColumn(), хотя есть много предупреждений от затмения, например: TableColumn является сырье типа. Ссылки на общий тип TableColumn должны быть параметризованы.

Удостоверьтесь, что у вас есть правильный импорт: import javafx.scene.control.TableColumn; и ничего не от Java Swing.