JavaFX组合框,点击项目

时间:2017-01-14 20:00:12

标签: java javafx combobox

我的问题如下,

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

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

我制作了以下代码:

CREATE PROCEDURE dbo.GenerateTable
(
    @SourceTable VARCHAR(128),
    @TargetTable VARCHAR(128)
)    
AS
BEGIN
    DECLARE @SQL NVARCHAR(4000) = N'
        SELECT * INTO ' + QUOTENAME(@TargetTable) + '
        FROM ' + QUOTENAME(@SourceTable) + '
        -- any false returning condition will do
        WHERE 1 = 0'
    EXEC (@SQL)
END
GO

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

但是我的问题是,当组合框中只有1个项目时,请说" item1"。然后用户重新打开组合框并点击" item1"再一次,它不会重做行动。

enter image description here

它只会打印该行" Item Clicked"当一个新的'单击项目。

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

提前致谢!

2 个答案:

答案 0 :(得分: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);
    }
}

在这种情况下,当用户“重新选择”相同的选项时,永远不需要重复动作,因为代码始终确保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);
    }
}

答案 1 :(得分:0)

这个想法是在ListView窗格上设置一个侦听器,该窗格在您单击ComboBox时出现。一旦将ComboBox首次加载到JavaFX场景中,便创建了ListView实例。因此,我们在ComboBox上添加了一个侦听器以检查它何时出现在场景中,然后通过“ lookup”方法获得ListView并向其添加侦听器。

private EventHandler<MouseEvent> cboxMouseEventHandler;

private void initComboBox() {
    ComboBox<String> comboBox = new ComboBox<String>();
    comboBox.getItems().add("Item 1");
    comboBox.getItems().add("Item 2");
    comboBox.getItems().add("Item 3");

    comboBox.sceneProperty().addListener((a,oldScene,newScene) -> {
        if(newScene == null || cboxMouseEventHandler != null)
            return;
            
        ListView<?> listView = (ListView<?>) comboBox.lookup(".list-view");
        if(listView != null) {
            cboxMouseEventHandler = (e) -> {
                Platform.runLater(()-> {
                    String selectedValue = (String) listView.getSelectionModel().getSelectedItem();
                    if(selectedValue.equals("Item 1"))
                        System.out.println("Item 1 clicked");
                });
            }; // cboxMouseEventHandler
        
            listView.addEventFilter(MouseEvent.MOUSE_PRESSED, cboxMouseEventHandler); 
        } // if
    });
} // initComboBox