在 ComboBox 列表视图的末尾添加一个按钮

Ska*_*rtt 1 java listview combobox javafx fxml

我需要创建一个组合框,它的列表视图末尾可以有一个按钮。此列表可以添加或删除项目,并在项目数超过 5 时显示滚动条。此外,选择项目时此列表视图不会自行关闭。

如何添加“新项目”按钮,如下面的屏幕截图所示?

在此输入图像描述

这是源代码:

helloApplication.java

package com.example.demo;

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

import java.io.IOException;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
        Scene scene = new Scene(fxmlLoader.load(), 320, 240);
        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }

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

HelloController.java

package com.example.demo;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox;
import javafx.scene.control.skin.ComboBoxListViewSkin;

import java.net.URL;
import java.util.ResourceBundle;

public class HelloController implements Initializable {

    @FXML
    private ComboBox<String> frequencyPlanComboBox;

    @Override
    public void initialize(URL pURL, ResourceBundle pResourceBundle) {
        frequencyPlanComboBox.getItems()
                             .addAll("aaa", "bbb", "ccc");
        ComboBoxListViewSkin<String> comboBoxListViewSkin = new ComboBoxListViewSkin<String>(frequencyPlanComboBox);
        comboBoxListViewSkin.setHideOnClick(false);
        frequencyPlanComboBox.setSkin(comboBoxListViewSkin);
    }
}
Run Code Online (Sandbox Code Playgroud)

你好视图.fxml

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

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>

<VBox alignment="CENTER" spacing="20.0" xmlns="http://javafx.com/javafx/null" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.demo.HelloController">
    <padding>
        <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
    </padding>

    <Label fx:id="welcomeText" />
   <ComboBox fx:id="frequencyPlanComboBox" prefWidth="150.0" visibleRowCount="5" />
</VBox>
Run Code Online (Sandbox Code Playgroud)

Jam*_*s_D 6

编辑版本:

正如评论中所指出的,OP 中的模型在列表视图之外有按钮,因此无需滚动到列表视图底部即可看到该按钮。您可以通过创建覆盖该方法的自定义皮肤来实现此目的getPopupContent()

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Bounds;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.control.skin.ComboBoxListViewSkin;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;

import java.net.URL;
import java.util.ResourceBundle;

public class HelloController implements Initializable {

    @FXML
    private ComboBox<String> frequencyPlanComboBox;

    @Override
    public void initialize(URL pURL, ResourceBundle pResourceBundle) {

        for (int i = 1 ; i <=20 ;i++) {
            frequencyPlanComboBox.getItems().add("Item "+i);
        }

        ComboBoxListViewSkin<String> comboBoxListViewSkin = new ComboBoxListViewSkin<String>(frequencyPlanComboBox) {
            private Button button = new Button("Add New");

            private VBox pane = new VBox();
            {
                pane.setStyle("-fx-background-color: -fx-control-inner-background;");
            }

            @Override
            public Node getPopupContent() {
                Node defaultContent = super.getPopupContent();
                defaultContent.setManaged(true);
                pane.getChildren().setAll(defaultContent, button);
                return pane ;
            }
        };
        comboBoxListViewSkin.setHideOnClick(false);
        frequencyPlanComboBox.setSkin(comboBoxListViewSkin);

    }
}
Run Code Online (Sandbox Code Playgroud)

这是最初的解决方案,可能不太理想:

将空值添加到组合框项目列表的末尾,并使用显示该值的按钮的自定义列表单元格。

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.control.skin.ComboBoxListViewSkin;

import java.net.URL;
import java.util.ResourceBundle;

public class HelloController implements Initializable {

    @FXML
    private ComboBox<String> frequencyPlanComboBox;

    @Override
    public void initialize(URL pURL, ResourceBundle pResourceBundle) {
        frequencyPlanComboBox.getItems()
                .addAll("aaa", "bbb", "ccc", null);
        ComboBoxListViewSkin<String> comboBoxListViewSkin = new ComboBoxListViewSkin<String>(frequencyPlanComboBox);
        comboBoxListViewSkin.setHideOnClick(false);
        frequencyPlanComboBox.setSkin(comboBoxListViewSkin);

        frequencyPlanComboBox.setCellFactory(lv -> new ListCell<>() {
            private Button button = new Button("Add New...");
            {
                button.setOnAction(e -> {
                    /*
                    Do something
                     */
                    System.out.println("Button pressed");
                });
            }
            @Override
            protected void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);
                if (empty) {
                    setText("") ;
                    setGraphic(null);
                } else if (item == null) {
                    setText("");
                    setGraphic(button);
                } else {
                    setText(item);
                    setGraphic(null);
                }
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

您可能想尝试一下该单元格的样式,这样它就不会显示为选中状态。

  • 当然,这会起作用,但缺点是用户不会知道该按钮的存在,除非他们滚动到组合框项目的底部。问题中的模型似乎显示它位于可滚动列表之外。 (2认同)