在我的阶段,我像往常一样在程序的顶部插入了一个菜单栏。我想在stage中的另一个上下文中为ALT键(连同箭头键)提供一些逻辑。但每次按下ALT和箭头时,我也会无意中浏览菜单栏的菜单。
我想避免这种情况,或者更好地完全禁用这种助记行为。将所有菜单的助记词解析属性设置为false失败了。我也尝试了这种方法,但没有成功:
menubar.addEventFilter(KeyEvent.ANY, e -> e.consume());
或者您可以重写MenuBar皮肤。Javafx已经做出选择(或者这是一个错误?),当按下ALT键时,焦点将被赋予MenuBar,而不是释放,这是Eclipse、Netbean、......更重要的是,当按下或释放ALT_GRAPH键时,焦点不应被赋予MenuBar。
这是我提出的补丁。请注意,只有第一个差异是相关的,最后一个差异只是为了在无法访问代码时编译代码。基本上,我已经将“firstMenuRunnable”拆分为3个函数
>
仅当按下F10键时才使用FirstMenuRunTable
当菜单栏有焦点且按下ALT键时,使用DeclesionKeyPressed
当菜单栏没有焦点且ALT键被释放时,使用focusOnFirstMenuOnKeyReleased
因此,可以使用标准行为,允许加速器使用ALT键,而无需菜单栏获取焦点。
--- com/sun/javafx/scene/control/skin/MenuBarSkin.java in C:\Program Files (x86)\Java\jdk1.8.0_131\javafx-src.zip
+++ C:\Users\daniel\dev\xxx\Layout\src\com\stimulus\control\MenuBarSkin.java
@@ -372,12 +491,21 @@
scene.getAccelerators().put(acceleratorKeyCombo, firstMenuRunnable);
// put focus on the first menu when the alt key is pressed
+ scene.addEventFilter(KeyEvent.KEY_PRESSED, e -> {
+ altDown = false;
+ });
scene.addEventHandler(KeyEvent.KEY_PRESSED, e -> {
- if (e.isAltDown() && !e.isConsumed()) {
- firstMenuRunnable.run();
+ if (e.isAltDown() && !e.isConsumed() && e.getCode().equals(KeyCode.ALT)) {
+ deselectMenusOnKeyPressed.run();
+ altDown = true;
}
});
+ scene.addEventHandler(KeyEvent.KEY_RELEASED, e -> {
+ if (altDown) {
+ focusOnFirstMenuOnKeyReleased.run();
+ }
});
+ });
ParentTraversalEngine engine = new ParentTraversalEngine(getSkinnable());
engine.addTraverseListener(this);
@@ -434,7 +453,50 @@
}
};
+ private boolean menuDeselectedOnKeyPressed = false;
+ Runnable deselectMenusOnKeyPressed = new Runnable() {
+ public void run() {
+ /*
+ ** check that this menubar's container has contents,
+ ** and that the first item is a MenuButton....
+ ** otherwise the transfer is off!
+ */
+ menuDeselectedOnKeyPressed = false;
+ if (container.getChildren().size() > 0) {
+ if (container.getChildren().get(0) instanceof MenuButton) {
+// container.getChildren().get(0).requestFocus();
+ if (focusedMenuIndex >= 0) {
+ unSelectMenus();
+ menuDeselectedOnKeyPressed = true;
+ }
+ }
+ }
+ }
+ };
+ Runnable focusOnFirstMenuOnKeyReleased = new Runnable() {
+ public void run() {
+ /*
+ ** check that this menubar's container has contents,
+ ** and that the first item is a MenuButton....
+ ** otherwise the transfer is off!
+ */
+ if (container.getChildren().size() > 0) {
+ if (container.getChildren().get(0) instanceof MenuButton) {
+// container.getChildren().get(0).requestFocus();
+ if (focusedMenuIndex == -1 && !menuDeselectedOnKeyPressed) {
+ unSelectMenus();
+ menuModeStart(0);
+ openMenuButton = ((MenuBarButton) container.getChildren().get(0));
+ openMenu = getSkinnable().getMenus().get(0);
+ openMenuButton.setHover();
+ }
+ }
+ }
+ }
+ };
+
private boolean pendingDismiss = false;
// For testing purpose only.
@@ -650,9 +712,23 @@
menuButton.textProperty().bind(menu.textProperty());
menuButton.graphicProperty().bind(menu.graphicProperty());
menuButton.styleProperty().bind(menu.styleProperty());
+ // patch because MenuButtonSkin.AUTOHIDE is private
+ final String AUTOHIDE;
+ {
+ try {
+ Class<?> clazz = MenuButtonSkin.class;
+// System.out.println("fields = " + Arrays.asList(clazz.getDeclaredFields()).toString());
+ Field field = clazz.getDeclaredField("AUTOHIDE");
+ field.setAccessible(true);
+ AUTOHIDE = (String) field.get(this);
+ field.setAccessible(false);
+ } catch (NoSuchFieldException | SecurityException | IllegalAccessException | IllegalArgumentException ex) {
+ throw new UnsupportedOperationException(ex);
+ }
+ }
menuButton.getProperties().addListener((MapChangeListener<Object, Object>) c -> {
- if (c.wasAdded() && MenuButtonSkin.AUTOHIDE.equals(c.getKey())) {
- menuButton.getProperties().remove(MenuButtonSkin.AUTOHIDE);
+ if (c.wasAdded() && AUTOHIDE.equals(c.getKey())) {
+ menuButton.getProperties().remove(AUTOHIDE);
menu.hide();
}
});
下面是我的菜单栏的完整代码:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.stimulus.control;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.Skin;
/**
*
* @author daniel
*/
public class CustomMenuBar extends MenuBar {
public CustomMenuBar() {
}
public CustomMenuBar(Menu... menus) {
super(menus);
}
@Override
protected Skin<?> createDefaultSkin() {
return new MenuBarSkin(this) {
};
}
}
当按下ALT时,第一个菜单获得焦点,当菜单具有焦点时,无论是否按下ALT,箭头键都会在它们之间导航。因此,为了防止这种行为,您需要防止第一个菜单在按下ALT时获得焦点。
查看MenuBarSkin类的构造函数源代码,我们可以找到解决方案:
public MenuBarSkin(final MenuBar control) {
...
Utils.executeOnceWhenPropertyIsNonNull(control.sceneProperty(), (Scene scene) -> {
scene.getAccelerators().put(acceleratorKeyCombo, firstMenuRunnable);
// put focus on the first menu when the alt key is pressed
scene.addEventHandler(KeyEvent.KEY_PRESSED, e -> {
if (e.isAltDown() && !e.isConsumed()) {
firstMenuRunnable.run();
}
});
});
...
}
正如您所猜测的,解决方案是在ALT关闭时使用事件,但需要将EventHandler添加到场景中,而不是菜单栏中:
scene.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
// your desired behavior
if(event.isAltDown())
event.consume();
}
});
因此,我仍然有点了解JavaFX,我能够禁止在文本框中输入文本,但我不知道如何防止右键单击时出现上下文菜单。有人知道如何防止右键单击时弹出默认上下文菜单吗?`
我正在使用MasterDetailPage并在其中使用动作条。我已经禁用和隐藏的标志,图标和后退按钮的动作条。但当我尝试从左到右从左侧滑动时,一个空白菜单列表打开。我不知道为什么会这样。我如何禁用操作条的这个。我不想要菜单列表这就是为什么我禁用后退按钮,图标。当我从左到右滑动时,我如何禁用这个从左到右滑动的菜单?
如何从操作栏禁用“选项”菜单项? 我做了我自己的自定义栏,用于显示*. png标志,但我不想显示选项菜单的三个点按钮。 我试图找到一些解决办法,但没有任何效果。
我想在Stage中添加一个JavaFX菜单栏,但是让它使用Mac的系统菜单栏。 我的问题是使用: 不起作用。我认为问题在于我的主要方法不是JavaFX应用程序的一部分。我的主要方法如下所示: SURPG_Mac.class和SURPG_Main.class是扩展 JavaFX 应用程序的类。 我有另一个设置GUI的类,一个带有BorderPane的阶段。我有另一个具有公共静态方法的类,可以调用它来
感谢阅读。我试图用css编辑一个菜单栏,但是菜单项没有改变。 我意识到菜单栏的部分是:菜单栏,菜单,菜单项,但最后一个不能正常工作。帮助 我正在使用场景生成器。
当助记字符添加到菜单文本中时,我们必须按Alt键才能显示助记下划线。如何让菜单助记下划线始终出现在我们按Alt之前?