JavaFX - ListView不会从fxml填充数据

时间:2017-01-10 11:35:56

标签: java listview javafx javafx-8 fxml

我正在尝试使用fxml填充列表视图,但在运行我的程序时,方法setCellFactory以某种方式不会被我的ListView调用。 是否有人可以帮助我解释如何修复我的代码?

listviewContoller.java - >

public class ListViewController implements Initializable {

    @SuppressWarnings("rawtypes")
    @FXML
    private ListView listView;

    private ArrayList<String> arrayList = new ArrayList<>();

    @SuppressWarnings("rawtypes")
    ObservableList observableList = FXCollections.observableArrayList();

    @SuppressWarnings("unchecked")
    @Override
    public void initialize(URL location, ResourceBundle resources) {
            arrayList.add("String 1");
            arrayList.add("String 2");
            arrayList.add("String 3");
            arrayList.add("String 4");
            observableList.setAll(arrayList);
            listView.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
                @Override
                public ListCell<String> call(ListView<String> param) {
                    return new ListViewCell();
                }
            });
    }
}

ListViewCell.java - &gt;

public class ListViewCell extends ListCell<String> {

    @Override
    public void updateItem(String string, boolean empty) {
        super.updateItem(string, empty);
        if(string != null) {
            Data data = new Data();
            data.setInfo(string);
            setGraphic(data.getBox());
        } else {
            Data data = new Data();
            data.setInfo("AAAA");
            setGraphic(data.getBox());
        }
    }
}

Data.java - &gt;

public class Data  implements Initializable{

    @FXML
    private HBox hBox;

    @FXML
    private ImageView imageListCell;

    @FXML
    private Label labelListCell;


    @Override
    public void initialize(URL location, ResourceBundle resources) {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/Tracker/UI/listCellItem.fxml"));
        try {
            loader.load();
        } catch (IOException e){
            throw new RuntimeException(e);
        }
    }

    public void setInfo(String string) {
        labelListCell.setText(string);
    }

    public HBox getBox() {
        return hBox;
    }
}

2 个答案:

答案 0 :(得分:2)

调用

setCellFactory ,但您使用的是不以任何方式显示内容的单元格:

创建Data的实例不会加载fxml,如果没有加载fxml,getBox()将始终返回null

BTW:重用Data以避免重新加载fxml是个好主意。

通常在这种情况下,您可以使用从fxml加载的内容创建自定义Node类型:

public class Data extends HBox {

    public Data() {
        // load fxml here
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/Tracker/UI/listCellItem.fxml"));
        loader.setController(this);
        loader.setRoot(this);
        try {
            loader.load();
        } catch (IOException ex) {
            throw new IllegalStateException(ex);
        }
    }

    @FXML
    private ImageView imageListCell;

    @FXML
    private Label labelListCell;

    public void setInfo(String string) {
        labelListCell.setText(string);
    }

}

<强> listCellItem.fxml

<!-- no fx:controller attribute allowed here -->
<fx:root type="javafx.scene.layout.HBox" xmlns:fx="http://javafx.com/fxml/1">
    <!-- contents of the root tag of the old fxml should be copied here -->
</fx:root>

请注意,您还应复制旧fxml的根元素的所有属性,但要复制fx:controller属性。

public class ListViewCell extends ListCell<String> {

    private final Data data;

    public ListViewCell() {
        this.data = new Data();
        setGraphic(this.data);
    }

    @Override
    public void updateItem(String string, boolean empty) {
        super.updateItem(string, empty);

        data.setInfo(string == null ? "AAAA" : string);
    }
}

此外,您从未设置items属性的新值:

@Override
public void initialize(URL location, ResourceBundle resources) {
    arrayList.add("String 1");
    arrayList.add("String 2");
    arrayList.add("String 3");
    arrayList.add("String 4");
    observableList.setAll(arrayList);
    listView.setItems(observableList);
    ...
}

此外,为什么不简单地添加@SuppressWarnings("rawtypes")作为类型参数???

而不是使用@SuppressWarnings("unchecked")<String>

答案 1 :(得分:0)

您可以直接在列表视图中添加对象

在下面的示例中,我在fxml中创建了一个列表项,并使用for循环在列表视图中添加该项

参见示例

的来源

ListViewExample FXML代码

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

<?import javafx.scene.control.ListView?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane id="AnchorPane" prefHeight="389.0" prefWidth="471.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="customlistview.ListViewExampleController">
  <children>
      <ListView fx:id="listView" layoutX="14.0" layoutY="14.0" prefHeight="389.0" prefWidth="517.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0" />
  </children>
</AnchorPane>

ListViewExampleController代码

package customlistview;

    import java.io.IOException;
    import java.net.URL;
    import java.util.ResourceBundle;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.fxml.FXMLLoader;
    import javafx.fxml.Initializable;
    import javafx.scene.control.ListCell;
    import javafx.scene.control.ListView;
    import javafx.util.Callback;
    import javafx.scene.layout.Pane;

    /**
     *
     * @author hemant-pc
     */
    public class ListViewExample implements Initializable {

        @FXML
        private ListView listView;

        @FXML
        Pane pane;

        public ListViewExample() {
        }

        @Override
        public void initialize(URL url, ResourceBundle rb) {
            try {
                ObservableList<Pane> list = FXCollections.observableArrayList();
                for (int i = 1; i <= 10; i++) {
                    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("ListItem.fxml"));
                    Pane listItem = fxmlLoader.load();
                    ListItemController controller = fxmlLoader.getController();
                    controller.setText("List Item " + i);
                    list.add(listItem);
                }
                listView.getItems().addAll(list);
            } catch (IOException ex) {
                Logger.getLogger(ListViewExample.class.getName()).log(Level.SEVERE, null, ex);
            }

        }

    }

ListItem FXML代码

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

    <?import javafx.scene.control.Button?>
    <?import javafx.scene.control.Label?>
    <?import javafx.scene.layout.Pane?>

    <Pane fx:id="pane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="65.0" prefWidth="317.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="customlistview.ListItemController">
       <children>
          <Label fx:id="label" layoutX="35.0" layoutY="6.0" prefHeight="50.0" prefWidth="117.0" text="ListItem1" />
          <Button fx:id="button" layoutX="201.0" layoutY="19.0" mnemonicParsing="false" onAction="#ButtonClick" text="Button" />
       </children>
    </Pane>

ListItemController代码

 package customlistview;

    import java.net.URL;
    import java.util.ResourceBundle;
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.Alert;
    import javafx.scene.control.Label;

    /**
     * FXML Controller class
     *
     * @author hemant-pc
     */
    public class ListItemController implements Initializable {

        @FXML
        Label label;

        /**
         * Initializes the controller class.
         */
        @Override
        public void initialize(URL url, ResourceBundle rb) {
            // TODO
        }

        @FXML
        public void ButtonClick(ActionEvent event) {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setContentText(label.getText());
            alert.showAndWait();
        }

        public void setText(String string) {
            label.setText(string);
        }

        public String getText() {
            return label.getText();
        }

    }

<强>快照

enter image description here