将标题添加到JavaFX ContextMenu

时间:2015-11-16 04:21:48

标签: javafx

是否可以为JavaFX TableView ContextMenu添加标题?

现在,我添加了一个MenuItem,我已将其标记为已禁用(通过menuTitle.setDisable(true)),但是使用某些样式设置(不透明度)进行渲染,我还没有想出如何覆盖。< / p>

代码示例 -

import java.util.function.Function;
import java.util.stream.IntStream;

import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.CheckMenuItem;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class TableWithContextMenu extends Application {

    @Override
    public void start(Stage primaryStage) {
        TableView<Item> table = new TableView<>();
        table.getColumns().add(column("Item", Item::nameProperty));
        table.getColumns().add(column("Value", Item::valueProperty));

        BooleanProperty globalSelection = new SimpleBooleanProperty();

        table.setRowFactory(t -> {
            TableRow<Item> row = new TableRow<>();
            ContextMenu contextMenu = new ContextMenu();
            MenuItem menuTitle = new MenuItem("Menu Title");
            menuTitle.setDisable(true);

            MenuItem item2 = new MenuItem("Do something else");
            item2.setOnAction(e -> System.out.println("Do something else with " + row.getItem().getName()));

            CheckMenuItem item3 = new CheckMenuItem("Global selection");
            item3.selectedProperty().bindBidirectional(globalSelection);

            contextMenu.getItems().addAll(menuTitle, item2, new SeparatorMenuItem(), item3);

            row.emptyProperty().addListener((obs, wasEmpty, isEmpty) -> {
                if (isEmpty) {
                    row.setContextMenu(null);
                } else {
                    row.setContextMenu(contextMenu);
                }
            });
            return row ;
        });

        IntStream.rangeClosed(1, 25).mapToObj(i -> new Item("Item "+i, i)).forEach(table.getItems()::add);

        primaryStage.setScene(new Scene(new BorderPane(table), 800, 600));
        primaryStage.show();
    }

    private <S,T> TableColumn<S,T> column(String title, Function<S, ObservableValue<T>> property) {
        TableColumn<S,T> col = new TableColumn<>(title);
        col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
        return col ;
    }

    public static class Item {
        private final IntegerProperty value = new SimpleIntegerProperty();
        private final StringProperty name = new SimpleStringProperty();

        public Item(String name, int value) {
            setName(name);
            setValue(value);
        }

        public final IntegerProperty valueProperty() {
            return this.value;
        }

        public final int getValue() {
            return this.valueProperty().get();
        }

        public final void setValue(final int value) {
            this.valueProperty().set(value);
        }

        public final StringProperty nameProperty() {
            return this.name;
        }

        public final String getName() {
            return this.nameProperty().get();
        }

        public final void setName(final String name) {
            this.nameProperty().set(name);
        }


    }

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

修改 下面发布的解决方案适用于此示例。但是,在处理多个FXML时,除非我清除样式类然后应用自定义样式,否则它不起作用。我发布了我的工作代码here来证明这个问题。

2 个答案:

答案 0 :(得分:4)

在CSS样式类MenuItem中指定了禁用menu-item:disabled的不透明度。要完全摆脱不透明度,您还需要覆盖已禁用Label名为MenuItem的{​​{1}}内的样式类。只需通过在您自己的css文件中指定它来覆盖该样式:

示例:

menu-item:disabled .label

您可能不希望其他不应该是标题的禁用菜单项具有相同的样式。在这种情况下,您只需将样式类添加到标题.menu-item:disabled { -fx-opacity: 1.0; } .menu-item:disabled .label { -fx-opacity: 1.0; }

MenuItem

然后css将是:

ContextMenu contextMenu = new ContextMenu();
MenuItem titleItem = new MenuItem("Title");
titleItem.setDisable(true);
titleItem.getStyleClass().add("context-menu-title");

编辑:您可能不希望标题与其他菜单项具有相同的.context-menu-title:disabled { -fx-opacity: 1.0; } .context-menu-title:disabled .label { -fx-opacity: 1.0; } 样式。可以通过为标题:hover设置:disabled:hover来解决此问题。 E.g:

MenuItem

答案 1 :(得分:0)

您无法为ContextMenu添加标题。

ContextMenu从PopupWindow扩展而来,不允许窗口装饰或标题栏。

来自文档:

  

PopupWindow是一个没有窗口装饰或标题栏的辅助窗口。它不会在操作系统中显示为顶级窗口。它通常用于工具提示,如通知,下拉框,菜单等。