Может ли JavaFX 8 установить строку меню по умолчанию?

Тривиальное игрушечное приложение со строкой экранного меню можно написать так на Java FX 8:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {
    public static void main(final String[] args) throws Exception {
        launch(Main.class, args);
    }

    @Override
    public void start(Stage stage) throws Exception {
        MenuBar menuBar = new MenuBar();
        Menu fileMenu = new Menu("File");
        MenuItem newNotebookMenuItem = new MenuItem("New Notebook...");
        newNotebookMenuItem.setAccelerator(KeyCombination.keyCombination("Meta+N"));
        newNotebookMenuItem.setOnAction(event -> { System.out.println("Action fired"); });
        fileMenu.getItems().add(newNotebookMenuItem);
        menuBar.getMenus().add(fileMenu);
        menuBar.setUseSystemMenuBar(true);

        VBox root = new VBox();
        root.getChildren().add(menuBar);
        Scene scene = new Scene(root, 400, 350);
        stage.setScene(scene);
        stage.show();
    }
}

Это может подойти для создания игрушечных приложений, таких как калькуляторы, где есть только одно окно, и приложение закрывается, когда закрывается последнее окно, но мое приложение основано на документах. Когда в приложении, основанном на документах, нет открытых документов, нет открытых окон, но меню должно оставаться видимым, чтобы пользователь мог открыть новый документ.

Обычный способ сделать это — setDefaultMenuBar в com.apple.eawt API, но это не очень удобно, потому что:

  1. Установка строки меню оттуда приводит к зависанию приложения (возможно, какая-то несовместимость между AWT и JavaFX — этого не происходит с тем же приложением, которое работает как чистый Swing).
  2. Это требует от меня создания javafx MenuBar для реальных окон, но JMenuBar для строки меню по умолчанию, и JavaFX не позволяет мне повторно использовать мои классы действий, поэтому ужасные адаптеры в конечном итоге будут написаны для преодоления разрыва.

Есть ли правильный способ установить это, которого я еще не нашел? Я ожидал найти такой метод в приложении (некоторые сообщения в списках рассылки намекали, что он может оказаться там), но похоже, что он все еще отсутствует.


person Trejkaz    schedule 27.06.2014    source источник
comment
Вы можете создать запрос функции JavaFX.   -  person jewelsea    schedule 21.01.2015


Ответы (3)


В настоящее время мой трюк заключается в следующем:

Pane pane = new Pane();
pane.maxWidth(1);
pane.maxHeight(1);
pane.resize(1, 1);
pane.getChildren().add(menuBar);
Scene scene = new Scene(pane,1,1);
scene.setFill(null);
primaryStage.initStyle(StageStyle.TRANSPARENT);
primaryStage.setWidth(1);
primaryStage.setHeight(1);
primaryStage.setScene(scene);
primaryStage.show();

Я ни для чего не использую этот этап. Он также должен быть невидимым. Раздражает и уродливо, но это работает.

Другим печальным фактом является то, что я должен настроить любое окно так, чтобы оно имело одинаковую строку меню... Это может сработать, а может и не сработать для вас.

person msj121    schedule 08.01.2015

Вот еще одна возможность без каких-либо взломов сцены, но имейте в виду, что она использует частные API:

List<MenuBase> menus = new ArrayList<>();
menus.add(GlobalMenuAdapter.adapt(fileMenu));

Toolkit.getToolkit().getSystemMenu().setMenus(menus);

Важно! Это решение предназначено только для OS X, поэтому вам все равно нужно добавить свое меню в сцену для других операционных систем.

person Sebastian S    schedule 21.01.2015
comment
Он использует частные API-интерфейсы com.sun.javafx, поэтому я думаю, что он официально не поддерживается, но, похоже, хорошо работает с OS X Oracle Java 8. Я связываю его с вызовом Platform.setImplicitExit(false);, чтобы остановить автоматическое закрытие приложения при закрытии последнего окна. - person jewelsea; 21.01.2015

Попробуйте использовать System.setProperty("apple.laf.useScreenMenuBar", "true");

для получения дополнительной информации см.:

https://developer.apple.com/library/mac/documentation/java/Reference/Java_PropertiesRef/Articles/JavaSystemProperties.html

и

https://developer.apple.com/library/mac/documentation/java/Conceptual/Java14Development/00-Intro/JavaDevelopment.html

Надеюсь, это поможет!

person user1525478    schedule 01.08.2014
comment
Это работает для AWT/Swing, но не для JavaFX, который не основан на AWT. - person Trejkaz; 05.08.2014