JavaFX组合框,点击项目

Déj*_* vu 0 java combobox javafx

我的问题如下,

为了这个问题,我在一个新项目中重现了这个问题.

假设我有一个带有组合框的应用程序,那里可能有一个或多个项目.我希望当用户点击组合框中的某个项目时会发生"某事".

我制作了以下代码:

        obsvList.add("item1");

        cbTest.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                System.out.println("Item clicked");
            }
        });
Run Code Online (Sandbox Code Playgroud)

这在应用程序启动并且第一次选择项目时有效.当组合框中有2个或更多项目时(当用户单击项目1,然后单击项目2,然后单击项目1时),这也适用

但是我的问题是,当组合框中只有1个项目时,让我们说"item1".然后用户重新打开组合框并再次单击"item1",然后它将不会重做动作.

在此输入图像描述

只有在单击"新建"项目时,它才会打印"项目单击"行.

我希望它能说清楚我遇到的问题是什么,如果没有请求澄清,我会在需要的地方给出.

提前致谢!

Jam*_*s_D 5

组合框的功能是向用户显示可供选择的选项列表.当您使用意味着选择的控件时,您应该确保UI始终与所选的选项一致.如果这样做,那么当用户"重新选择"相同选项时(因为UI已经处于所需状态),"重复动作"是没有意义的.一种方法是在组合框的值上使用绑定或侦听器:

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class ComboBoxExample extends Application {

    @Override
    public void start(Stage primaryStage) {
        ComboBox<Item> choices = new ComboBox<>();
        for (int i = 1 ; i <=3 ; i++) {
            choices.getItems().add(new Item("Choice "+i, "These are the details for choice "+i));
        }

        Label label = new Label();

        choices.valueProperty().addListener((obs, oldItem, newItem) -> {
            label.textProperty().unbind();
            if (newItem == null) {
                label.setText("");
            } else {
                label.textProperty().bind(newItem.detailsProperty());
            }
        });

        BorderPane root = new BorderPane();
        root.setCenter(label);
        root.setTop(choices);

        Scene scene = new Scene(root, 400, 400);
        primaryStage.setScene(scene);
        primaryStage.show();

    }

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

        public Item(String name, String details) {
            this.name = name ;
            setDetails(details) ;
        }

        public String getName() {
            return name ;
        }

        @Override
        public String toString() {
            return getName();
        }

        public final StringProperty detailsProperty() {
            return this.details;
        }


        public final String getDetails() {
            return this.detailsProperty().get();
        }


        public final void setDetails(final String details) {
            this.detailsProperty().set(details);
        }



    }

    public static void main(String[] args) {
        launch(args);
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,当用户"重新选择"相同的选项时,从不需要重复动作,因为代码始终确保UI与所选择的内容一致(如果用户选择了该选项,则无需执行任何操作已选择的选项).通过在显示详细信息的UI部分中使用绑定(在这种情况下只是一个简单的标签),我们可以确保,如果数据在外部发生变化,UI将保持最新状态.(显然在实际应用中,这可能要复杂得多,但基本策略仍然完全相同.)

另一方面,如果用户选择相同的功能,则需要重复动作的功能被更好地视为向用户呈现一组"动作".对此的适当控制是菜单,带按钮的工具栏和MenuButtons.

一组可重复动作的示例是:

import java.util.stream.Collectors;
import java.util.stream.Stream;

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.MenuButton;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class MenuButtonExample extends Application {

    @Override
    public void start(Stage primaryStage) {
        MenuButton menuButton = new MenuButton("Items");
        Label label = new Label();

        Item[] items = new Item[3];
        for (int i = 1 ; i <=3 ; i++) {
            items[i-1] = new Item("Item "+i);
        }

        for (Item item : items) {
            MenuItem menuItem = new MenuItem(item.getName());
            menuItem.setOnAction(e -> item.setTimesChosen(item.getTimesChosen() + 1));
            menuButton.getItems().add(menuItem);
        }

        label.textProperty().bind(Bindings.createStringBinding(() -> 
            Stream.of(items)
                .map(item -> String.format("%s chosen %d times", item.getName(), item.getTimesChosen()))
                .collect(Collectors.joining("\n")), 
            Stream.of(items)
                .map(Item::timesChosenProperty)
                .collect(Collectors.toList()).toArray(new IntegerProperty[0])));

        BorderPane root = new BorderPane();
        root.setCenter(label);
        root.setTop(menuButton);

        Scene scene = new Scene(root, 400, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static class Item {
        private final String name ;
        private final IntegerProperty timesChosen = new SimpleIntegerProperty();

        public Item(String name) {
            this.name = name ;
        }

        public String getName() {
            return name ;
        }

        @Override
        public String toString() {
            return getName();
        }

        public final IntegerProperty timesChosenProperty() {
            return this.timesChosen;
        }


        public final int getTimesChosen() {
            return this.timesChosenProperty().get();
        }


        public final void setTimesChosen(final int timesChosen) {
            this.timesChosenProperty().set(timesChosen);
        }



    }

    public static void main(String[] args) {
        launch(args);
    }
}
Run Code Online (Sandbox Code Playgroud)