2016-03-31 2 views
2

enter image description herejavafx: как программно менять элементы ComboBox в TableCell?

как вы можете видеть уже, у меня есть TableView, который имеет два столбца ComboBoxTableCell.

это предок значение

ObservableList<String> ancestors = FXCollections.observableArrayList("1", "2", "3", "4", "5", "6", "7", "8", "9", "10"); 
ancestorColumn.setCellFactory(ComboBoxTableCell.forTableColumn(ancestors)); 
descendantColumn.setCellFactory(ComboBoxTableCell.forTableColumn()); 

Map<String, List<String>> descendantMap = new HashMap(); 
descendantMap.put("1", Arrays.asList("A", "B", "C")); 
descendantMap.put("2", Arrays.asList("Z", "L", "C")); 
descendantMap.put("3", Arrays.asList("A", "B", "R")); 
descendantMap.put("4", Arrays.asList("C", "B", "E")); 
descendantMap.put("5", Arrays.asList("A", "E", "C")); 
descendantMap.put("6", Arrays.asList("M", "V", "T")); 
descendantMap.put("7", Arrays.asList("A", "G", "F")); 
descendantMap.put("8", Arrays.asList("J", "O", "N")); 
descendantMap.put("9", Arrays.asList("X", "G", "E")); 
descendantMap.put("10", Arrays.asList("H", "I", "J")); 

теперь, когда я изменить выбор предков выпадающего списка, соответствующий потомок выпадающий должны заполняться с элементами в карте этого ключа. т. е. если я изменяю предка на «1» в строке таблицы, то выпадающая папка потомка в той же строке должна заполняться («A», «B», «C»). Как достичь этого?

EDIT: привет, я сделал это, и это работает. но им не уверен, если его правильный способ сделать это. может кто-то сказать мне, если это правильный способ сделать это?

descendantColumn.setCellFactory(param -> { 
    return new TableCell() { 
     ComboBox box = new ComboBox(); 
     @Override 
     public void updateItem(String item, boolean empty) { 
      if(!empty) { 
       setGraphic(box); 
       ancestorColumn.getCellObservableValue(getIndex()).addListener((o, ov, nv) -> { 
        if(nv != null) { 
         box.setItems(descendantMap.get(nv)); 
        } 
       }); 
      } else { 
       setGraphic(null); 
      } 
     } 
    }; 
}); 

ответ

2

Я создал пример того, как я это сделаю, но, пожалуйста: я создаю это в течение получаса или около того - код далеко не идеален, нормально?

Вот полный код ...

FXML:

<?xml version="1.0" encoding="UTF-8"?> 
<!-- 
    Do not edit this file it is generated by e(fx)clipse from ../src/application/TableTest.fxgraph 
--> 

<?import java.lang.*?> 
<?import javafx.geometry.Insets?> 
<?import javafx.scene.control.TableColumn?> 
<?import javafx.scene.control.TableView?> 
<?import javafx.scene.layout.BorderPane?> 

<BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="application.TableTestController"> 

    <center> 
     <TableView fx:id="tableView"> 
      <columns> 
       <TableColumn fx:id="tableColumnText" text="Text" prefWidth="150"/> 
       <TableColumn fx:id="tableColumnFlag" text="Flag" prefWidth="50"/> 
       <TableColumn fx:id="tableColumnAncestor" text="Ancestor" prefWidth="75"/> 
       <TableColumn fx:id="tableColumnDescendant" text="Descendant" prefWidth="100"/> 
       <TableColumn fx:id="tableColumnPoints" text="Points" prefWidth="75"/> 
      </columns> 
      <BorderPane.margin> 
       <Insets top="5" left="5" right="5" bottom="5"/> 
      </BorderPane.margin> 
     </TableView> 
    </center> 
</BorderPane> 

класс данных Модель (тот, который, представляющий собой одну строку в TableView):

package application; 

import javafx.beans.property.BooleanProperty; 
import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.SimpleBooleanProperty; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 

public class TableTestObject { 

    private StringProperty text = new SimpleStringProperty(""); 
    private BooleanProperty flag = new SimpleBooleanProperty(false); 
    private StringProperty ancestor = new SimpleStringProperty(""); 
    private StringProperty descendant = new SimpleStringProperty(""); 
    private IntegerProperty points = new SimpleIntegerProperty(0); 

    public final StringProperty textProperty() { 
     return this.text; 
    } 

    public final String getText() { 
     return this.textProperty().get(); 
    } 

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

    public final BooleanProperty flagProperty() { 
     return this.flag; 
    } 

    public final boolean isFlag() { 
     return this.flagProperty().get(); 
    } 

    public final void setFlag(final boolean flag) { 
     this.flagProperty().set(flag); 
    } 

    public final StringProperty ancestorProperty() { 
     return this.ancestor; 
    } 

    public final String getAncestor() { 
     return this.ancestorProperty().get(); 
    } 

    public final void setAncestor(final String ancestor) { 
     this.ancestorProperty().set(ancestor); 
    } 

    public final StringProperty descendantProperty() { 
     return this.descendant; 
    } 

    public final String getDescendant() { 
     return this.descendantProperty().get(); 
    } 

    public final void setDescendant(final String descendant) { 
     this.descendantProperty().set(descendant); 
    } 

    public final IntegerProperty pointsProperty() { 
     return this.points; 
    } 

    public final int getPoints() { 
     return this.pointsProperty().get(); 
    } 

    public final void setPoints(final int points) { 
     this.pointsProperty().set(points); 
    } 
} 

Основной класс:

package application; 

import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 

public class Main extends Application { 
    @Override 
    public void start(Stage stage) throws Exception { 
     FXMLLoader loader = new FXMLLoader(getClass().getResource("TableTest.fxml")); 
     Parent root = loader.load(); 
     Scene scene = new Scene(root, 1200, 800); 
     stage.setScene(scene); 
     stage.show(); 
    } 

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

TableTestController (тот , что делает обязательный материал):

package application; 

import java.util.Arrays; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 

import javafx.beans.property.SimpleObjectProperty; 
import javafx.beans.value.ChangeListener; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.fxml.FXML; 
import javafx.scene.control.CheckBox; 
import javafx.scene.control.ComboBox; 
import javafx.scene.control.ContentDisplay; 
import javafx.scene.control.Spinner; 
import javafx.scene.control.SpinnerValueFactory; 
import javafx.scene.control.TableCell; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.scene.control.cell.PropertyValueFactory; 

public class TableTestController { 

    @FXML 
    private TableView<TableTestObject> tableView; 
    @FXML 
    private TableColumn<TableTestObject, String> tableColumnText; 
    @FXML 
    private TableColumn<TableTestObject, TableTestObject> tableColumnFlag; 
    @FXML 
    private TableColumn<TableTestObject, TableTestObject> tableColumnAncestor; 
    @FXML 
    private TableColumn<TableTestObject, TableTestObject> tableColumnDescendant; 
    @FXML 
    private TableColumn<TableTestObject, TableTestObject> tableColumnPoints; 

    private Map<String, List<String>> descendantMap; 
    private ObservableList<String> ancestorList; 

    @FXML 
    protected void initialize() { 

     descendantMap = new HashMap<>(); 
     descendantMap.put("1", Arrays.asList("A", "B", "C")); 
     descendantMap.put("2", Arrays.asList("Z", "L", "C")); 
     descendantMap.put("3", Arrays.asList("A", "B", "R")); 
     descendantMap.put("4", Arrays.asList("C", "B", "E")); 
     descendantMap.put("5", Arrays.asList("A", "E", "C")); 
     descendantMap.put("6", Arrays.asList("M", "V", "T")); 
     descendantMap.put("7", Arrays.asList("A", "G", "F")); 
     descendantMap.put("8", Arrays.asList("J", "O", "N")); 
     descendantMap.put("9", Arrays.asList("X", "G", "E")); 
     descendantMap.put("10", Arrays.asList("H", "I", "J")); 

     ancestorList = FXCollections.observableArrayList(descendantMap.keySet()); 

     ObservableList<TableTestObject> data = FXCollections.observableArrayList(); 
     TableTestObject test = new TableTestObject(); 
     test.setText("Test"); 
     test.setFlag(true); 
     test.setPoints(1); 
     data.add(test); 

     tableView.setItems(data); 

     tableColumnText.setCellValueFactory(new PropertyValueFactory<>("text")); 
     tableColumnFlag.setCellValueFactory(param -> new SimpleObjectProperty<TableTestObject>(param.getValue())); 
     tableColumnAncestor.setCellValueFactory(param -> new SimpleObjectProperty<TableTestObject>(param.getValue())); 
     tableColumnDescendant.setCellValueFactory(param -> new SimpleObjectProperty<TableTestObject>(param.getValue())); 
     tableColumnPoints.setCellValueFactory(param -> new SimpleObjectProperty<TableTestObject>(param.getValue())); 

     tableColumnFlag.setCellFactory(param -> new TableCell<TableTestObject, TableTestObject>() { 
      @Override 
      protected void updateItem(TableTestObject item, boolean empty) { 
       super.updateItem(item, empty); 
       if (empty) { 
        setText(null); 
       } else { 
        CheckBox cb = new CheckBox(); 
        cb.selectedProperty().bindBidirectional(item.flagProperty()); 
        setGraphic(cb); 
        setContentDisplay(ContentDisplay.GRAPHIC_ONLY); 
       } 
      } 
     }); 
     tableColumnAncestor.setCellFactory(param -> new TableCell<TableTestObject, TableTestObject>() { 
      @Override 
      protected void updateItem(TableTestObject item, boolean empty) { 
       super.updateItem(item, empty); 
       if (empty) { 
        setText(null); 
       } else { 
        ComboBox<String> cb = new ComboBox<>(ancestorList); 
        cb.getSelectionModel().selectedItemProperty().addListener((ChangeListener<String>) (observable, oldValue, newValue) -> { 
         item.ancestorProperty().set(newValue); 
         System.out.println(item.descendantProperty().get()); 
        }); 
        setGraphic(cb); 
        setContentDisplay(ContentDisplay.GRAPHIC_ONLY); 
       } 
      } 
     }); 
     tableColumnDescendant.setCellFactory(param -> new TableCell<TableTestObject, TableTestObject>() { 
      @Override 
      protected void updateItem(TableTestObject item, boolean empty) { 
       super.updateItem(item, empty); 
       if (empty) { 
        setText(null); 
       } else { 
        ComboBox<String> cb = new ComboBox<>(); 
        item.ancestorProperty().addListener((ChangeListener<String>) (observable, oldValue, newValue) -> { 
         item.descendantProperty().set(""); 
         cb.setItems(FXCollections.observableArrayList(descendantMap.get(newValue))); 
        }); 
        cb.getSelectionModel().selectedItemProperty().addListener((ChangeListener<String>) (observable, oldValue, newValue) -> { 
         item.descendantProperty().set(newValue); 
         System.out.println(item.descendantProperty().get()); 
        }); 
        setGraphic(cb); 
        setContentDisplay(ContentDisplay.GRAPHIC_ONLY); 
       } 
      } 
     }); 
     tableColumnPoints.setCellFactory(param -> new TableCell<TableTestObject, TableTestObject>() { 
      @Override 
      protected void updateItem(TableTestObject item, boolean empty) { 
       super.updateItem(item, empty); 
       if (empty) { 
        setText(null); 
       } else { 
        Spinner<Integer> spinner = new Spinner<>(); 
        spinner.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(-5, +5, item.getPoints())); 
        spinner.valueProperty().addListener((ChangeListener<Integer>) (observable, oldValue, newValue) -> { 
         item.pointsProperty().set(newValue); 
         System.out.println(item.pointsProperty().get()); 
        }); 
        setGraphic(spinner); 
        setContentDisplay(ContentDisplay.GRAPHIC_ONLY); 
       } 
      } 
     }); 
    } 
} 

Еще раз: Контроллер - это тот, который выполняет привязку. С Lambdas код почти читабельен, но вы все равно должны его переработать.

Приветствия, Daniel

+0

мой среды IDE NetBeans не распознан импорт javafx.scene.control.Spinner, как вы в состоянии компонент? – Doberon

+0

Я пользователь Eclipse, поэтому я не уверен на 100 процентов. Я полагаю, он должен работать из коробки. Какую версию Java вы используете? – dzim

Смежные вопросы