如何为组合框和列表中的选项添加标签?

Posted

技术标签:

【中文标题】如何为组合框和列表中的选项添加标签?【英文标题】:How do you add labels to the options in combobox and list? 【发布时间】:2015-01-08 11:35:37 【问题描述】:

我阅读了以下文档,http://docs.oracle.com/javafx/2/ui_controls/combo-box.htm,但没有找到与我的需求相似的任何内容。我正在寻找一种将我的选项分组在组合框中的方法。假设我的组合框是持续时间。我有以下选择: - 过去 1 小时、过去 2 小时、过去 24 小时、上周、过去 30 天、过去 3 个月、去年。我要在组合框中添加标签“短持续时间”和“长持续时间”。用户只能选择一个,但它看起来有点像:

Short Duration
Last Hour
Last 2 hours
Last 24 Hours

Long Duration
Last Month
Last year

短持续时间和长持续时间就像标题一样。你不能点击它们。

谢谢!

注意:我不是在说Label ab = new Label ("Short duration");

这是我的代码(我尝试在组合框中插入标签作为选项,但您可以选择它)

ComboBox combobox_print_options = new ComboBox();
combobox_print_options.setPromptText("Choose the button you wish to click");

Label table = new Label("Table");
combobox_print_options.getItems().addAll(
table, 
"a",
"b");

【问题讨论】:

【参考方案1】:

为您的组合框创建一个项目类,声明它是否是可选项目。 (您还可以为此添加其他有用的 API,例如一个方便的访问器来表示它所代表的时间量。)

然后使用一个单元格工厂来禁用代表不可选择项的单元格:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class ComboBoxWithSections extends Application 

    @Override
    public void start(Stage primaryStage) 
        ComboBox<ComboBoxItem> combo = new ComboBox<>();
        combo.getItems().addAll(
            new ComboBoxItem("Short Duration", false),
            new ComboBoxItem("Last Hour",      true),
            new ComboBoxItem("Last 2 hours",   true),
            new ComboBoxItem("Last 24 hours",  true),
            new ComboBoxItem("",               false),
            new ComboBoxItem("Long Duration",  false),
            new ComboBoxItem("Last Month",     true),
            new ComboBoxItem("Last Year",      true)            
        );

        combo.setCellFactory(listView -> new ListCell<ComboBoxItem>() 
            @Override
            public void updateItem(ComboBoxItem item, boolean empty) 
                super.updateItem(item, empty);
                if (empty) 
                    setText(null);
                    setDisable(false);
                 else 
                    setText(item.toString());
                    setDisable(! item.isSelectable());
                
            
        );

        BorderPane root = new BorderPane(null, combo, null, null, null);
        primaryStage.setScene(new Scene(root, 250, 400));
        primaryStage.show();
    

    public static class ComboBoxItem 
        private final String name ;
        private final boolean selectable ;

        public ComboBoxItem(String name, boolean selectable) 
            this.name = name ;
            this.selectable = selectable ;
        

        public String getName() 
            return name ;
        

        public boolean isSelectable() 
            return selectable ;
        

        @Override
        public String toString() 
            return name ;
        
    

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

更新这已经回答了elsewhere,但我会使用CSS PseudoClass 和外部CSS 文件来更改标题的样式:

添加

    final PseudoClass header = PseudoClass.getPseudoClass("section-header");

改成start(...)方法,修改cell factory的updateItem(...)方法如下:

        public void updateItem(ComboBoxItem item, boolean empty) 
            super.updateItem(item, empty);
            if (empty) 
                setText(null);
                setDisable(false);
                pseudoClassStateChanged(header, false);
             else 
                setText(item.toString());
                setDisable(! item.isSelectable());
                pseudoClassStateChanged(header, ! item.isSelectable());
            
        

现在将 css 文件附加到 Scene:

    scene.getStylesheets().add("combo-box-with-sections.css");

css 文件可能看起来像

combo-box-with-sections.css:

.combo-box-popup .list-cell 
    -fx-padding: 4 0 4 20 ;


.combo-box-popup .list-cell:section-header 
    -fx-font: italic 10pt sans-serif ;
    -fx-padding: 4 0 4 5 ;

【讨论】:

是的,这正是我想要的!虽然它很长: 是的,但是您可以获得项目的实际类的额外好处,而不是使用String。因此,现在您可以在其中添加您需要的 API,而不必打开 Strings 来确定(例如)某些内容是否在正确的时间范围内。换句话说,大部分开销都是你想在一个真正的应用程序中做的事情。 我明白你的意思!我了解您的大部分代码,但如果您在答案中添加一些 cmets 以确保阅读您的代码的人理解它,我会很高兴。老实说,我不太了解 .setCellFactory 但它按我想要的方式工作。 它只是一个标准的电池工厂......请参阅Cell Javadocs以获得相当全面的解释。 任何想法如何使标题更明显?粗体还是缩进内部元素?有可能吗?

以上是关于如何为组合框和列表中的选项添加标签?的主要内容,如果未能解决你的问题,请参考以下文章

组合选项框和组合框以将记录添加到右表

列表框的示例

将两个选项按钮与单个组合框链接,用于不同的行源[关闭]

Qt c++ 依赖组合框和依赖标签

颜色组合框和自定义颜色选择器

WPF 组合框和数据绑定到其他类