2014-01-02 3 views
6

У меня есть таблица, и у нее есть строка с флажком.Получить значение флажка в таблице в JavaFX

Что я хочу сделать, это нажать кнопку «Я хочу узнать, какие флажки отмечены, а какие нет. Пока мне удалось создать флажки в таблице. Код выглядит следующим образом.

The output so far

public class TTEs implements Initializable{ 

@FXML 
private TableView<TestObject> tableReport; 

@FXML 
private TableColumn<TestObject, String> name; 

@FXML 
private TableColumn<TestObject, Boolean> checkbox; 


@FXML 
public void getValues(){   
    //the method will get what check boxes are checked (this part is the problem) 
} 


@Override 
public void initialize(URL arg0, ResourceBundle arg1) { 


    ObservableList<TestObject> data = FXCollections.observableArrayList(); 
    data.add(new TestObject("Test 1", true)); 
    data.add(new TestObject("Test 2", false)); 

    tableReport.setItems(data); 

    name.setCellValueFactory(new PropertyValueFactory<TestObject, String>("name")); 
    checkbox.setCellValueFactory(new PropertyValueFactory<TestObject, Boolean>("checked")); 

    checkbox.setCellFactory(new Callback<TableColumn<TestObject, Boolean>, TableCell<TestObject, Boolean>>() { 

      public TableCell<TestObject, Boolean> call(TableColumn<TestObject, Boolean> p) { 
       return new CheckBoxTableCell<TestObject, Boolean>(); 
      } 
     }); 

} 


//CheckBoxTableCell for creating a CheckBox in a table cell 
public static class CheckBoxTableCell<S, T> extends TableCell<S, T> { 
    private final CheckBox checkBox; 
    private ObservableValue<T> ov; 

    public CheckBoxTableCell() { 
     this.checkBox = new CheckBox(); 
     this.checkBox.setAlignment(Pos.CENTER); 

     setAlignment(Pos.CENTER); 
     setGraphic(checkBox); 
    } 

    @Override public void updateItem(T item, boolean empty) { 
     super.updateItem(item, empty); 
     if (empty) { 
      setText(null); 
      setGraphic(null); 
     } else { 
      setGraphic(checkBox); 
      if (ov instanceof BooleanProperty) { 
       checkBox.selectedProperty().unbindBidirectional((BooleanProperty) ov); 
      } 
      ov = getTableColumn().getCellObservableValue(getIndex()); 
      if (ov instanceof BooleanProperty) { 
       checkBox.selectedProperty().bindBidirectional((BooleanProperty) ov); 
      } 
     } 
    } 
} 

}

когда я debugg, я обнаружил, что,

 ov = getTableColumn().getCellObservableValue(getIndex()); 
     if (ov instanceof BooleanProperty) { 
      checkBox.selectedProperty().bindBidirectional((BooleanProperty) ov); 
     } 

в вышеприведенном Condtion, он никогда не заходит внутрь, если. Означает, что экземпляр ovis i = nota, если имеет значение Boolean. Но когда я печатаю класс OV,

System.out.println(ov.getClass().getName()); 

он печатает, как

javafx.beans.property.ReadOnlyObjectWrapper

ReadOnlyObjectWrapper подкласс BooleanProperty

+0

Дубликат - http://stackoverflow.com/questions/13459936/get- row-values-of-ticked-checkbox-in-jtable – user3029101

+2

Noo, то есть в java swing. Мое приложение использует javaFX. Там много различий. – Ravindu

+0

gotozero ответ ниже работал для меня и занял около минуты, чтобы реализовать. Никаких изменений кода не требуется, если вы используете fxml. –

ответ

4
package checkboxtablecelltest; 

import javafx.application.Application; 
import javafx.beans.property.BooleanProperty; 
import javafx.beans.property.SimpleBooleanProperty; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 
import javafx.beans.value.ChangeListener; 
import javafx.beans.value.ObservableValue; 
import javafx.collections.FXCollections; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.SelectionMode; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.scene.control.cell.CheckBoxTableCell; 
import javafx.scene.control.cell.PropertyValueFactory; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.HBox; 
import javafx.stage.Stage; 

/** 
* 
* @author reegan 
*/ 
public class CheckBoxTableCellTest extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     final TableView<Person> tableView = new TableView<Person>(); 
     tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); 
     tableView.setItems(FXCollections.observableArrayList(
       new Person("Robert", "Plant"), 
       new Person("Neil", "Young"), 
       new Person("Willie", "Nelson"), 
       new Person("Natalie", "Merchant"))); 
     tableView.getItems().get(3).setVegetarian(true); 
     final TableColumn<Person, String> firstNameCol = new TableColumn<Person, String>("First Name"); 
     final TableColumn<Person, String> lastNameCol = new TableColumn<Person, String>("Last Name"); 
     final TableColumn<Person, Boolean> vegetarianCol = new TableColumn<Person, Boolean>("Vegetarian"); 
     tableView.getColumns().addAll(firstNameCol, lastNameCol, vegetarianCol); 
     firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 
     lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); 
     vegetarianCol.setCellValueFactory(new PropertyValueFactory<Person, Boolean>("vegetarian")); 
     vegetarianCol.setCellFactory(CheckBoxTableCell.forTableColumn(vegetarianCol)); 
     vegetarianCol.setEditable(true); 
     tableView.setEditable(true); 

     final BorderPane root = new BorderPane(); 
     root.setCenter(tableView); 

     final HBox controls = new HBox(5); 
     final Button infoButton = new Button("Show details"); 
     infoButton.setOnAction(new EventHandler<ActionEvent>() { 
      @Override 
      public void handle(ActionEvent event) { 
       for (Person p : tableView.getItems()) { 
        System.out.printf("%s %s (%svegetarian)%n", p.getFirstName(), 
          p.getLastName(), p.isVegetarian() ? "" : "not "); 
          System.out.println(tableView.getSelectionModel().getSelectedItems()); 

       } 
       System.out.println(); 
      } 
     }); 
     controls.getChildren().add(infoButton); 
     root.setBottom(controls); 

     Scene scene = new Scene(root, 300, 400); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

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

    public static class Person { 

     private StringProperty firstName; 
     private StringProperty lastName; 
     private BooleanProperty vegetarian; 

     public Person(String firstName, String lastName) { 
      this.firstName = new SimpleStringProperty(firstName); 
      this.lastName = new SimpleStringProperty(lastName); 
      this.vegetarian = new SimpleBooleanProperty(false); 
     } 

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

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

     public boolean isVegetarian() { 
      return vegetarian.get(); 
     } 

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

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

     public void setVegetarian(boolean vegetarian) { 
      this.vegetarian.set(vegetarian); 
     } 

     public StringProperty firstNameProperty() { 
      return firstName; 
     } 

     public StringProperty lastNameProperty() { 
      return lastName; 
     } 

     public BooleanProperty vegetarianProperty() { 
      return vegetarian; 
     } 
    } 
} 

`

+1

Не просто разместите стену кода без каких-либо объяснений –

+0

Извините @StealthRabbi мой английский очень плохой поэтому я не объясню в своем коде .... после этого я напишу объяснение. спасибо за ваши советы ... –

5

Перебор модели данных вашей TableView проверки логическое значение, которое связано с каждым CheckBox.

@FXML 
public void getValues(){   
    ObservableList<TestObject> data = tableReport.getItems(); 

    for (TestObject item : data){ 
     //check the boolean value of each item to determine checkbox state 
    } 
} 
+0

Пробовал это, но булевское значение не сопоставляется с флажком. Не знаю, почему и как. (хотя я установил логическое значение как «true», он не установил флажок) – Ravindu

+0

обновил вопрос :) – Ravindu

2

Основная проблема с вашим подходом является использование CheckBoxTableCell: Ячейка является сильно повторно «рендеринг» машины. Если вы попытаетесь добавить состояние, например, переменную CheckBox, у вас проблемы.

Самое простое решение проблемы заключается в том, чтобы каждый раз устанавливать флажок. Следующий код обеспечивает рабочую колонку флажок:

public static class Member { 
    private StringProperty myName; 
    private BooleanProperty myCheck; 

    public Member(String name, boolean checked) { 
     myName = new SimpleStringProperty(name); 
     myCheck = new SimpleBooleanProperty(checked); 
    } 

    public StringProperty nameProperty() { return myName; }  
    public BooleanProperty checkProperty() { return myCheck; } 
} 

VBox testTable6(VBox box) { // check box bind to cell property 
    ObservableList<Member> members = FXCollections.observableArrayList(); 

    members.add(new Member("peter", true)); 
    members.add(new Member("gernot", true)); 
    members.add(new Member("fritz", false)); 

    TableView<Member> table = new TableView<Member>(); 
    table.prefHeightProperty().bind(box.heightProperty()); 
    table.setItems(members); 

    TableColumn<Member,String> c1 = new TableColumn<Member,String>("Name"); 
    c1.setCellValueFactory(new PropertyValueFactory<Member,String>("name")); 
    table.getColumns().add(c1); 

    TableColumn<Member,Boolean> c2 = new TableColumn<Member,Boolean>("Membercheck"); 
    c2.setCellValueFactory(new PropertyValueFactory<Member,Boolean>("check")); 
    c2.setCellFactory(column -> new TableCell<Member, Boolean>(){ 
     public void updateItem(Boolean check, boolean empty) { 
      super.updateItem(check, empty); 
      if (check == null || empty) { 
       setGraphic(null); 
      } else { 
       CheckBox box = new CheckBox(); 
       BooleanProperty checked = (BooleanProperty)column.getCellObservableValue(getIndex()); 
       box.setSelected(checked.get()); 
       box.selectedProperty().bindBidirectional(checked); 
       setGraphic(box); 
      } 
     } 
    } 
      ); 
    table.getColumns().add(c2); 

    box.getChildren().addAll(table); 
    return box; 
} 

Как двунаправленного свойства, привязанного слабое связывание, сбор carbage будет работать должным образом, даже если вы не можете отвязать явно.

Непроверенный актер на BooleanProperty не очень хороший стиль, так или иначе, извините. Рассмотрим для доступа весь объект с помощью:

... 
Member member = table.getItems().get(getIndex()); 
box.setSelected(member.checkProperty().get()); 
box.selectedProperty().bindBidirectional(member.checkProperty()); 
.... 

со стороны так: birdeirectional привязки не будет установлено выбранное свойство в тот момент, только если оно изменилось после! поэтому явное назначение:

box.setSelected(member.checkProperty().get()); 

является обязательным здесь.

12

Протестировано на Java 8.
Только 4 простых вещи.

1) Сделайте класс CheckBoxCellFactory. Поместите где-нибудь в свой проект.

public class CheckBoxCellFactory implements Callback { 
    @Override 
    public TableCell call(Object param) { 
     CheckBoxTableCell<Person,Boolean> checkBoxCell = new CheckBoxTableCell(); 
     return checkBoxCell; 
    } 
} 

2) Ваша модель класса. Например, человек.

public static class Person { 
    private SimpleBooleanProperty checked = new SimpleBooleanProperty(false); 
    // other columns here 

    public SimpleBooleanProperty checkedProperty() { 
     return this.checked; 
    } 

    public java.lang.Boolean getChecked() { 
     return this.checkedProperty().get(); 
    } 

    public void setChecked(final java.lang.Boolean checked) { 
     this.checkedProperty().set(checked); 
    } 

    // getter/setter for other columns 

} 

3) внесены изменения в файле FXML. Раздел вашего TableView -> TableColumn буду выглядеть следующим образом:

<TableColumn fx:id="checkBoxTableColumn" maxWidth="34.0" minWidth="26.0" prefWidth="34.0" resizable="false" sortable="false"> 
<cellValueFactory><PropertyValueFactory property="checked" /></cellValueFactory> 
<cellFactory><partarch.fx.CheckBoxCellFactory /></cellFactory> 
</TableColumn> 

4) Если вы хотите, чтобы ваш флажок быть редактируемые

  • 4,1 Открыть FXML в Scene Builder.
  • 4.2 Выберите столбец checkBox, а затем установите флажок «Редактируемое» в области «Свойства».
  • 4.3 Выберите TableView, содержащий ваш флажок, и сделайте то же самое (отметьте свойство «Редактируемый» в панели «Свойства»).

Реализация в двоичных файлов на SF и источник на GitHub

+0

Не работает. Сам флажок изменяется, когда пользователь нажимает на него, но значение не передается модели –

+0

@Mateus Viccari , вы можете посмотреть здесь [GitHub] (https://github.com/backtozero/PartArch) – gotozero

+2

@gotozero Этот ответ работал для меня дословно (все, что я сделал, больше не следовало вашим инструкциям). Большое вам спасибо за самый простой ответ. Это действительно правильный ответ и заслуживает большего внимания. –

1

Немного не по теме - но в Котлин вы можете сделать это:

isPvtColumn.cellFactory = Callback { CheckBoxTableCell<KeyWithProperties, Boolean>() } 

    isPvtColumn.cellValueFactory = Callback { 
     a -> a.value.private 
    } 

Это все есть на него

+0

очень полезен для меня, так как я не мог найти эту информацию в другом месте – ycomp

0

В методе инициализации переключите свой заводской настройку на тот, который предоставляется JavaFX:

@Override 
public void initialize(URL arg0, ResourceBundle arg1) { 

    ObservableList<TestObject> data = FXCollections.observableArrayList(); 
    data.add(new TestObject("Test 1", true)); 
    data.add(new TestObject("Test 2", false)); 

    tableReport.setItems(data); 

    name.setCellValueFactory(new PropertyValueFactory<TestObject, String>("name")); 
    checkbox.setCellValueFactory(new PropertyValueFactory<TestObject, Boolean>("checked")); 

    checkbox.setCellFactory(
     CheckBoxTableCell.forTableColumn(checkbox) 
    ); 

} 

Теперь ваши данные переплетены в колонну, и вы можете перемещаться по элементам и проверить для «проверил» поле:

@FXML 
public void getValues(){   
    ObservableList<TestObject> data = tableReport.getItems(); 

    for (TestObject item : data){ 
     //check the boolean value of each item to determine checkbox state 
    } 
} 
Смежные вопросы