【问题标题】:JavaFX8 list bindings similar to xamlJavaFX8 列表绑定类似于 xaml
【发布时间】:2015-05-16 12:26:04
【问题描述】:

我无法在 fxml 中将集合绑定到自定义模板。这里是我在 xaml 中的代码:

<ListView ItemsSource="{Binding PersonCollection}">
    <StackPanel Orientation="Horizontal">
        <Label Content="{Binding FirstName}"></Label>
        <ListView ItemsSource="{Binding MiddleNames}">
            <Label Content="{Binding}"></Label>
        </ListView>
        <Label Content="{Binding LastName}"></Label>
    </StackPanel>
</ListView>

这里是模型:

class Person
{
    String FirstName, LastName;
    String[] MiddleNames;
}

布局看起来类似于:

John Ivy
Robert Downey Junior
Max more middlenames in fact even thousands are possible lastname

是否可以将 oberservable 集合绑定到自定义模板? 我尝试了cellfactory,但无法理解它,因为每个人都只使用字符串。

【问题讨论】:

  • 什么是自定义模板?
  • 我扩展了我的问题以进一步解释设置。它的本质是,为集合中的每个项目应用模板。因此,对于 PersonCollection 中的每个项目,它都会生成一个水平堆栈面板、名字标签、姓氏标签和另一个带有模板的列表视图。
  • 您在哪里以及如何指定输入数据(例如 John Ivy、Robert Downey Junior 等)?它是静态的且永不更改的,还是在运行时更改的动态数据?你确定你真的想要一个ListView 这里(因为那会很奇怪)还是它实际上与 JavaFX ListView 完全不同? (我对 xaml 完全不熟悉)。
  • 数据在一种控制器中,在xaml中称为datacontext。并且可以更改数据。因此,如果我将另一个 Person 添加到 PersonCollection ,则 ListView 将添加此人员 ui(如果从集合中删除,则删除)。我真的不想要 ListView,真正的 ui 将是键值对和手风琴的混合,但它看起来很简单。我制作了一个快速(而且可怕的 :-D)模型:s8.postimg.org/l7jr1d5tx/image.png

标签: javafx javafx-8 fxml


【解决方案1】:

我不是 100% 确定这是您问题的答案,因为我对 xaml 完全不熟悉,但希望它是...

示例实施

该示例通过将模型对象(Person)设置到 FXML 加载器的命名空间中来工作,这允许您使用 FXML 中的绑定表达式来绑定到对象的属性。

在示例中,模型中最初有几个名称,您可以使用添加和删除按钮修改模型中的绑定列表,以在列表中添加或删除更多固定名称。

所有代码都放在一个名为 sample.names 的包中。

name-display.fxml

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

<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.layout.HBox?>

<?import javafx.geometry.Insets?>

<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Button?>
<VBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.names.NameDisplayController">
  <HBox prefHeight="150.0" prefWidth="220.0" spacing="5.0"  >
    <children>
      <Label fx:id="firstNameLabel" text="${person.firstName}" />
      <ListView fx:id="middleNameList" prefWidth="100.0" items = "${person.middleNames}" />
      <Label fx:id="lastNameLabel" text="${person.lastName}" />
    </children>
    <padding>
      <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
    </padding>
  </HBox>
  <HBox alignment="CENTER" spacing="30.0">
    <children>
      <Button mnemonicParsing="false" onAction="#addName" text="Add" />
      <Button mnemonicParsing="false" onAction="#removeName" text="Remove" />
    </children>
    <padding>
      <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
    </padding>
  </HBox>
</VBox>

NameDisplayApp.java

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

import java.io.IOException;

public class NameDisplayApp extends Application {

    @Override
    public void start(Stage stage) throws IOException {
        Person person = new Person(
                "Bruce",
                new String[] { "Simon", "Larry" },
                "Banner"
        );

        FXMLLoader loader = new FXMLLoader(
                getClass().getResource(
                        "name-display.fxml"
                )
        );
        loader.getNamespace().put(
                "person",
                person
        );
        Pane pane = loader.load();

        NameDisplayController controller = loader.getController();
        controller.setPerson(person);

        stage.setScene(new Scene(pane));
        stage.show();
    }

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

NameDisplayController.java

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;

public class NameDisplayController {
    private Person person;

    private ObservableList<String> sampleNames = FXCollections.observableArrayList(
            "George", "Henry", "Wallace"
    );

    public void setPerson(Person person) {
        this.person = person;
    }

    public void addName(ActionEvent actionEvent) {
        if (!sampleNames.isEmpty()) {
            person.getMiddleNames().add(
                sampleNames.remove(0)
            );
        }
    }

    public void removeName(ActionEvent actionEvent) {
        if (!person.getMiddleNames().isEmpty()) {
            sampleNames.add(
                    person.getMiddleNames().remove(0)
            );
        }
    }
}

Person.java

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

public class Person {
    public StringProperty firstName;
    public StringProperty lastName;

    private ObservableList<String> middleNames;

    public Person(String firstName, String[] middleNames, String lastName) {
        this.firstName   = new SimpleStringProperty(firstName);
        this.middleNames = FXCollections.observableArrayList(middleNames);
        this.lastName    = new SimpleStringProperty(lastName);
    }

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

    public StringProperty firstNameProperty() {
        return firstName;
    }

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

    public ObservableList<String> getMiddleNames() {
        return middleNames;
    }

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

    public StringProperty lastNameProperty() {
        return lastName;
    }

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

替代实现

可能还有其他(可能是更优选的方式)可以做到这一点 - 例如通过在代码中关联项目的绑定而不是 FXML(这是我通常做的)或使用依赖注入系统注入模型。有关注入方法的示例,请参见 afterburner.fx - 尽管我不知道 afterburner 是否也将模型对象放入 FXML 命名空间或只是注入控制器(如果它不注入 FXML 命名空间可能是一个很酷的补充,你可以要求它)。

【讨论】:

  • 这与我来的进度类似,但除了字符串之外,我无法模板化其他东西。如果我想要一个按钮或窗格列表怎么办?那可能吗?我什至对答案不满意。
  • @kadir 然后你必须指定一个 cellFactory。
  • 我正在尝试使用 ${property} 表示法将变量传递到我的工厂方法中,但它不起作用。这有什么限制吗?
  • @TravisTubbs 我知道没有限制。但我不知道你在做什么。我建议您使用minimal reproducible example 创建一个新问题,有人可能会查看并帮助您。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-27
  • 2012-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多