当前位置: 首页 > 知识库问答 >
问题:

我如何添加多个组合框到JavaFX,一旦一个项目被选中,费用显示在下面?

田骁
2023-03-14

我想向JavaFX添加多个组合框,在用户选择一个项目后,该项目的成本将显示在组合框下。此外,所有选定项目的总成本将显示在底部。我知道如何制作一个组合框来显示所选一个项目的成本,但不知道如何制作多个组合框并显示所选所有项目的成本

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.StringConverter;
import javafx.collections.FXCollections;

public class Animals extends Application {

    Stage window;
    Scene scene;
    Button button;
    ComboBox<Animal> comboBox = new ComboBox<Animal>();
    Text textNamePrice = new Text();

    static public TextField[] tfLetters = new TextField[37];

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        window = primaryStage;
        window.setTitle("ComboBox ");
        button = new Button("Submit");

        comboBox = new ComboBox<Animal>();

        comboBox.setConverter(new StringConverter<Animal>() {
            @Override
            public String toString(Animal object) {
                return object.getName();
            }

            @Override
            public Animal fromString(String string) {
                return null;
            }
        });

        comboBox.setItems(FXCollections.observableArrayList(new Animal("Dog", 30.12), new Animal("Cat", 23.23),
                new Animal("Bird", 15.0)));

        comboBox.valueProperty().addListener((obs, oldVal, newVal) -> {
            String selectionText = "Price of the " + newVal.getName() + " is : " + newVal.getPrice();

            System.out.println(selectionText);
            textNamePrice.setText(selectionText);
        });

        VBox layout = new VBox(10);
        layout.setPadding(new Insets(60, 60, 60, 60));
        layout.getChildren().addAll(comboBox, textNamePrice, button);

        scene = new Scene(layout, 500, 350);
        window.setScene(scene);
        window.show();
    }

    public class Animal {
        private String name;
        private Double price;

        public Double getPrice() {
            return price;
        }

        public String getName() {
            return name;
        }

        public Animal(String name, Double price) {
            this.name = name;
            this.price = price;
        }
    }
}

共有1个答案

裴钧
2023-03-14

使用自定义节点typeAnimalChooser显示组合框价格可能是最简单的方法。这样,可以在一个地方处理一个选择价格显示的功能。此外,您还可以根据选择提供价格属性,以便从应用程序类中对其进行汇总。

以下示例将所有这些AnimalChooser放在一个VBox中,并将侦听器添加到子列表中,以便在子列表中添加和删除侦听器,如果它被修改,这将允许您动态地将这些AnimalChooser添加/删除到/从VBox中,并且仍然可以获得正确更新的总和。

public class Animal {

    private final String name;
    // primitive type should be prefered here
    private final double price;

    public double getPrice() {
        return price;
    }

    public String getName() {
        return name;
    }

    public Animal(String name, double price) {
        this.name = name;
        this.price = price;
    }
}
public class AnimalChooser extends VBox {

    private final ComboBox<Animal> animalCombo;
    private final ReadOnlyDoubleWrapper price;
    private final Text text;

    public AnimalChooser(ObservableList<Animal> items) {
        setSpacing(5);
        animalCombo = new ComboBox<>(items);

        // converter for using a custom string representation of Animal in the
        // combobox
        animalCombo.setConverter(new StringConverter<Animal>() {

            @Override
            public String toString(Animal object) {
                return object == null ? "" : object.getName();
            }

            @Override
            public Animal fromString(String string) {
                if (string == null || string.isEmpty()) {
                    return null;
                } else {

                    // find suitable animal from list
                    Animal animal = null;

                    for (Animal item : items) {
                        if (string.equals(item.getName())) {
                            animal = item;
                            break;
                        }
                    }

                    return animal;
                }
            }

        });

        text = new Text();
        price = new ReadOnlyDoubleWrapper();

        getChildren().addAll(animalCombo, text);

        // bind price value to price property
        price.bind(Bindings.createDoubleBinding(new Callable<Double>() {

            @Override
            public Double call() throws Exception {
                Animal animal = animalCombo.getValue();
                return animal == null ? 0d : animal.getPrice();
            }
        }, animalCombo.valueProperty()));

        // bind text to content of Text node
        text.textProperty().bind(Bindings.when(animalCombo.valueProperty().isNull()).then("").otherwise(price.asString("%.2f $")));
    }

    public final double getPrice() {
        return this.price.get();
    }

    public final ReadOnlyDoubleProperty priceProperty() {
        return this.price.getReadOnlyProperty();
    }

}
@Override
public void start(Stage primaryStage) {

    VBox animalChoosers = new VBox(20);

    ObservableList<Animal> animals = FXCollections.observableArrayList(
            new Animal("cat", 1000.99),
            new Animal("dog", 20.50),
            new Animal("goldfish", 15.22)
    );

    final DoubleProperty total = new SimpleDoubleProperty();

    InvalidationListener listener = new InvalidationListener() {

        @Override
        public void invalidated(Observable observable) {
            double sum = 0d;
            for (Node n : animalChoosers.getChildren()) {
                AnimalChooser chooser = (AnimalChooser) n;
                sum += chooser.getPrice();
            }

            total.set(sum);
        }
    };

    // just in case you want to add AnimalChooser s dynamially to animalChoosers
    animalChoosers.getChildren().addListener(new ListChangeListener<Node>() {

        @Override
        public void onChanged(ListChangeListener.Change<? extends Node> c) {
            while (c.next()) {
                // add remove listeners updating the total
                for (Node n : c.getRemoved()) {
                    AnimalChooser chooser = (AnimalChooser) n;
                    chooser.priceProperty().removeListener(listener);
                }
                for (Node n : c.getAddedSubList()) {
                    AnimalChooser chooser = (AnimalChooser) n;
                    chooser.priceProperty().addListener(listener);
                }
            }

            listener.invalidated(null);
        }

    });

    for (int i = 0; i < 10; i++) {
        animalChoosers.getChildren().add(new AnimalChooser(animals));
    }

    BorderPane root = new BorderPane(animalChoosers);
    Text totalText = new Text();
    totalText.textProperty().bind(total.asString("total: %.2f $"));

    root.setBottom(totalText);
    BorderPane.setMargin(totalText, new Insets(20));

    Scene scene = new Scene(root);

    primaryStage.setScene(scene);
    primaryStage.show();
}
 类似资料:
  • 我正在开发一些学术性的JavaFX桌面应用程序。在创建注册表单时,我需要使用combobox/choicebox,但在这一步中我遇到了几个问题。组合框没有显示任何项目。我尝试了许多在堆栈溢出上找到的修复方法,但似乎都不起作用。我在分享我的主要观点。java控制器代码和我的FXML代码放在一边。 Main.java Controller.java FXML文件

  • 问题内容: 我需要一些帮助,将一些项目添加到中。因此,我有两个组合框,其中一个根据所选项目填充另一个。 我的问题是,用于新项目,它可以工作,但是如果我为组合框选择另一个选项,它将添加新项目,但先前的项目不见了-新项目下面有空白项目。 我以为每次我从第一个组合框选择一个新选项来清除第二个组合框的内容。所以我在第二个上使用了-但没有用。 我就是这样想的: 上面是第一次更改时执行的功能的一部分。 问题答

  • 我有一个简单的基于JavaFXML、scenebuilder和Derby数据库的双选项卡应用程序。有一个MainController类声明为: InputController类定义了第一个名为Input的选项卡。它编组一些基本数据,包括一个新帐户名称和一个复选框以指示帐户是否处于活动状态。收集输入后,它会通过DAO控制器类写入derby数据库中的表: 以下是DAO控制器类中的代码: DetailC

  • 我的情况是,我有一个comb-Box,通过javascript动态地填充整数值。 问题是当我点击项目选择它时,它仍然没有被选中,点击该项目后,我需要再次点击组合框外才能选中它。我不知道为什么? 我这样做的代码是(它是内表): 我如何填充组合中的项目是这样的: 我以前在wpf或任何其他应用程序中所做的是,我只是在combobox中单击要选择的项目,它就被选中了,但为什么我需要在项目上单击一次,然后在

  • 我创建了一个类,它有一个名为cards的面板,其布局是CardLAyout。我添加了卡片项目。在这个类中,我想通过调用layout来创建一个单独的方法,该方法将切换到下一张卡片。 } 正如你所看到的,我在卡片上添加了其他类的面板。我想做的是创建getNextCard()方法,该方法将当前活动的面板作为其参数。当我调用此功能时,它应该将当前活动的面板切换到我的CardLayout列表中的下一个面板。

  • 我试图创建一个垂直轮播,显示上一个和下一个项目。 我能得到这样的东西: 肖特 风景 如您所见,横向模式已经显示下一个和项目之前。我想在竖屏中获得相同的结果。这是我使用的代码: activity_main.xml: SliderItem: 滑块适配器: 主要活动: 希望你能帮助我