2017-01-15 4 views
2

Я не могу связать элементы TableView с ObservableList в FXML.Bind TableView элементов с ObservableList в FXML - Java FX

Все работает нормально, когда я устанавливаю materialTable.setItems (materialDataObservableList); в событии нажатия кнопки. Но я не хочу, чтобы кнопка знала о TableView, поэтому я хотел привязать свойство materialTable.items к свойству materialDataObservableList.

Что я делаю неправильно? Или, может быть, я не понимаю, как работает связывание ...

Спасибо за помощь!

<GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="464.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.xxx.sm.frontend.fx.MainSceneController"> 
/* 
*/ 
<children> 
    <VBox prefHeight="200.0" prefWidth="100.0"> 
     <children> 
      <Button fx:id="getMaterialsButton" mnemonicParsing="false" onAction="#getMaterialsButton" text="Get materials" /> 
      <TableView fx:id="materialTable" editable="true" prefHeight="413.0" prefWidth="600.0" items="${materialDataObservableList}" > 
       //Columns here 
       <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /> 
      </columnResizePolicy> 
      </TableView> 
     </children> 
    </VBox> 
</children> 

public class MainSceneController { 


private ObservableList<MaterialData> materialDataObservableList; 
public TableView materialTable; 
public Button getMaterialsButton; 

public void getMaterialsButton() { 
    getMaterialsFromRESTController(); 
} 

private void getMaterialsFromRESTController() { 
    MaterialClient controller = new MaterialClient(); 
    try { 
     materialDataObservableList = FXCollections.observableArrayList(controller.getMaterias()); 
    } catch (IOException e) { 
     System.out.println("Failed to connect to RESTController"); 
    } 
    //materialTable.setItems(materialDataObservableList); 
} 

public ObservableList<MaterialData> getMaterialDataObservableList() { 
    return materialDataObservableList; 
} 
} 

ответ

2

Если вы звоните getMaterialsFromRESTController() из конструктора MainSceneController «s (так он инициализируется как только контроллер доступен для FXMLLoader), затем

<TableView fx:id="materialTable" editable="true" prefHeight="413.0" prefWidth="600.0" 
    items="${controller.materialDataObservableList}" > 

будет Работа. (Обратите внимание, вы получаете доступ к свойству контроллера с ${controller.property}.)

Если нет, то вы можете изменить контроллер следующим образом, чтобы сделать его работу:

public class MainSceneController { 


    private final ObservableList<MaterialData> materialDataObservableList 
     = FXCollections.observableArrayList(); 
    public TableView materialTable; 
    public Button getMaterialsButton; 

    public void getMaterialsButton() { 
     getMaterialsFromRESTController(); 
    } 

    private void getMaterialsFromRESTController() { 
     MaterialClient controller = new MaterialClient(); 
     try { 
      materialDataObservableList.setAll(controller.getMaterias()); 
     } catch (IOException e) { 
      System.out.println("Failed to connect to RESTController"); 
     } 
    } 

    public ObservableList<MaterialData> getMaterialDataObservableList() { 
     return materialDataObservableList; 
    } 

} 

, а затем выше FXML должен работать.


Вот SSCCE:

BindTableItemsExample.fxml:

<?xml version="1.0" encoding="UTF-8"?> 

<?import javafx.scene.layout.BorderPane?> 
<?import javafx.scene.control.TableView?> 
<?import javafx.scene.control.TableColumn?> 
<?import javafx.scene.control.cell.PropertyValueFactory?> 
<?import javafx.scene.control.Button?> 
<?import javafx.geometry.Insets?> 

<BorderPane xmlns:fx="http://javafx.com/fxml/1" fx:controller="TableController"> 
    <center> 
     <TableView items="${controller.items}"> 
      <columns> 
       <TableColumn text="Item"> 
        <cellValueFactory><PropertyValueFactory property="name" /></cellValueFactory> 
       </TableColumn> 
      </columns> 
     </TableView> 
    </center> 
    <bottom> 
     <Button text="Load" onAction="#loadItems" BorderPane.alignment="center" > 
      <BorderPane.margin> 
       <Insets top="5" left="5" right="5" bottom="5"/> 
      </BorderPane.margin> 
     </Button> 
    </bottom> 
</BorderPane> 

TableController.java:

import java.util.List; 
import java.util.stream.Collectors; 
import java.util.stream.IntStream; 

import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.fxml.FXML; 

public class TableController { 

    private final ObservableList<Item> items = FXCollections.observableArrayList(); 

    @FXML 
    private void loadItems() { 
     items.setAll(createItems()); 
    } 

    private List<Item> createItems() { 
     return IntStream.rangeClosed(1, 100) 
       .mapToObj(i -> "Item "+i) 
       .map(Item::new) 
       .collect(Collectors.toList()); 
    } 

    public ObservableList<Item> getItems() { 
     return items ; 
    } 


    public static class Item { 
     private final StringProperty name = new SimpleStringProperty(); 

     public Item(String name) { 
      setName(name); 
     } 

     public final StringProperty nameProperty() { 
      return this.name; 
     } 

     public final java.lang.String getName() { 
      return this.nameProperty().get(); 
     } 

     public final void setName(final java.lang.String name) { 
      this.nameProperty().set(name); 
     } 

    } 
} 

BindTableItemsTest.java (класс приложения):

import java.io.IOException; 

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

public class BindTableItemsTest extends Application { 

    @Override 
    public void start(Stage primaryStage) throws IOException { 
     FXMLLoader loader = new FXMLLoader(getClass().getResource("BindTableItemsExample.fxml")); 
     primaryStage.setScene(new Scene(loader.load(), 600, 600)); 
     primaryStage.show(); 
    } 

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

Спасибо, это очень помогло мне! – user1803183

+0

Спасибо за полезный ответ. Я добавил 'initialize()' метод в 'TableController', чтобы загружать элементы без нажатия кнопки. Код доступен [здесь] (https://ideone.com/XZ6p1g), если он кому-то поможет. – c0der

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