#java #macos #javafx #javafx-8
#java #macos #javafx #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, но это не очень удобно, потому что:
- Установка строки меню оттуда зависает приложение (возможно, какая-то несовместимость между AWT и JavaFX — этого не происходит с тем же приложением, которое работает как чистый Swing.)
- Это требует от меня создания строки меню javafx для реальной Windows, но строки меню JMenuBar для строки меню по умолчанию, а JavaFX не позволяет мне повторно использовать мои классы действий, поэтому ужасные адаптеры в конечном итоге будут написаны для устранения разрыва.
Есть ли правильный способ установить это, который я просто еще не нашел? Я ожидал найти такой метод в приложении (некоторые сообщения в списке рассылки намекали, что он может оказаться там), но, похоже, он все еще отсутствует.
Комментарии:
1. Вы можете рассмотреть возможность создания запроса функции JavaFX .
Ответ №1:
В настоящее время мой трюк заключается в следующем:
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();
Я не использую этот этап ни для чего. Она также должна быть невидимой. Раздражает и некрасиво, но это работает.
Другой печальный факт заключается в том, что я должен установить для любого окна одинаковую строку меню…. Это может работать или не работать для вас.
Ответ №2:
Вот еще одна возможность без каких-либо взломов сцены, но имейте в виду, что она использует частные API:
List<MenuBase> menus = new ArrayList<>();
menus.add(GlobalMenuAdapter.adapt(fileMenu));
Toolkit.getToolkit().getSystemMenu().setMenus(menus);
Важно: это решение только для OS X, поэтому вам все равно нужно добавить свое меню в сцену для других операционных систем.
Комментарии:
1. Он использует частные
com.sun.javafx
API, поэтому я предполагаю, что он официально не поддерживается, но, похоже, хорошо работает с OS X Oracle Java 8. Я связываю его с вызовомPlatform.setImplicitExit(false);
, чтобы остановить автоматическое завершение работы приложения при закрытии последнего окна.
Ответ №3:
Попробуйте использовать System.setProperty("apple.laf.useScreenMenuBar", "true");
для получения дополнительной информации см.:
и
Надеюсь, это поможет!
Комментарии:
1. Это работает для AWT / Swing, но не для JavaFX, который не основан на AWT.