我有一个JavaFX按钮,当用户按Enter时触发。这会导致FileChooser打开。有些人(像我一样)可能会在FileChooser中点击Enter来保存文件。但是,这会导致保存按钮再次触发自身并再次打开FileChooser以保存新文件。用鼠标单击按钮(在FileChooser中)没有这个问题。
我以为从按钮中使用事件会解决这个问题,但它只使用GUI事件上的按钮,而不是FileChooser按钮。我尝试过寻找修改FileChooser的EventHandler以使用回车键的方法,但没有成功。
我还尝试过将焦点从按钮上移开并将其移动到父级(窗格),以便无法再次单击它。但是,有些按钮可以多次单击而无需再次重新关注它们。
我的代码示例如下所示(显然这将是扩展Application的更大类的一部分):
EventHandler<KeyEvent> enter = event -> {
if (event.getCode() == KeyCode.ENTER && event.getSource() instanceof Button) {
Button src = (Button) event.getSource();
src.fire();
}
event.consume();
};
Button b1 = new Button("Save");
b1.setOnKeyReleased(enter);
/* Called by .fire method */
b1.setOnAction(event -> {
/* Create the save dialog box */
FileChooser saveDialog = new FileChooser();
saveDialog.setTitle("Save");
/* Get file */
File f = saveDialog.showSaveDialog(stage);
/*
* ... do stuff with file ...
*/
});
注意:这个例子不是我的确切代码。相反,密钥释放事件是用于多个按钮的变量,而不仅仅是保存按钮(即b2.setOnKeyReleased(Enter);
b2.setOnAction(事件-
如何防止在用户在文件选择器中按 Enter 键时触发按钮?我不希望用户在没有鼠标的情况下陷入循环。我知道按Alt S也可以保存它,但我不能指望所有用户都知道这一点。
编辑:根据现在似乎已被删除的评论中的要求,以下是代码的可运行版本:
import java.io.File;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.HBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
public class ButtonTest extends Application {
@Override
public void start(Stage stage) throws Exception {
/* EventHandler to be used with multiple buttons */
EventHandler<KeyEvent> enter = event -> {
if (event.getCode() == KeyCode.ENTER && event.getSource() instanceof Button) {
Button src = (Button) event.getSource();
src.fire();
}
event.consume();
};
/* Create a new button */
Button b1 = new Button("Save");
Button b2 = new Button("Print");
/* Add event handlers */
b1.setOnKeyReleased(enter);
b2.setOnKeyReleased(enter);
/* Called by .fire method of save button */
b1.setOnAction(event -> {
/* Create the save dialog box */
FileChooser saveDialog = new FileChooser();
saveDialog.setTitle("Save");
/* Get file */
File f = saveDialog.showSaveDialog(stage);
/* ... do stuff with file ... */
});
/* Called by .fire method of print button */
b2.setOnAction(event -> System.out.println("Pressed"));
Scene scene = new Scene(new HBox(b1, b2));
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
我为文件添加了一个布尔值Chooser正在打开,它似乎对我有用,但我不得不拆分事件,否则它只会每隔一次触发打印按钮
public class Main extends Application {
private boolean fileChooserOpen = false;
@Override
public void start(Stage stage) throws Exception{
/* EventHandler to be used with multiple buttons */
EventHandler<KeyEvent> enterWithFileChooser = event -> {
if (!fileChooserOpen && event.getCode() == KeyCode.ENTER && event.getSource() instanceof Button) {
Button src = (Button) event.getSource();
src.fire();
fileChooserOpen = true;
}else {
fileChooserOpen = false;
}
event.consume();
};
EventHandler<KeyEvent> enter = event -> {
if (event.getCode() == KeyCode.ENTER && event.getSource() instanceof Button) {
Button src = (Button) event.getSource();
src.fire();
}
event.consume();
};
/* Create a new button */
Button b1 = new Button("Save");
Button b2 = new Button("Print");
/* Add event handlers */
b1.setOnKeyReleased(enterWithFileChooser);
b2.setOnKeyReleased(enter);
/* Called by .fire method of save button */
b1.setOnAction(event -> {
/* Create the save dialog box */
FileChooser saveDialog = new FileChooser();
saveDialog.setTitle("Save");
/* Get file */
File f = saveDialog.showSaveDialog(stage);
/* ... do stuff with file ... */
});
/* Called by .fire method of print button */
b2.setOnAction(event -> System.out.println("Pressed"));
Scene scene = new Scene(new HBox(b1, b2));
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) { launch(args); }
}
问题是从< code>onKeyReleased处理程序中触发< code >按钮。当您释放< kbd>ENTER键时,< code>FileChooser已被隐藏,并且< code>Stage已重新获得焦点,这意味着键释放事件被给予您的< code>Stage/按钮
。显然这会造成一个循环。
一种可能的解决方案是从onKeyPress
处理程序内部触发Button
。但是,这将提供与其他应用程序略有不同的行为,这是您的用户可能不期望/欣赏的。
另一种可能的解决方案是跟踪FileChooser
在触发Button
之前是否已打开,就像Matt在他的答案中所做的那样。
您似乎试图做的是允许用户使用ENTER键来触发Button
;这应该是Windows等平台上的默认行为。
不适合我。空格是触发按钮的唯一键。我认为这是因为回车键用于触发默认按钮,该按钮使用btn.setDefaultButton(true)设置;
对我来说,在Windows 10上使用JavaFX 11.0.2而不是JavaFX 8u202时,当< code >按钮具有焦点时按< kbd>ENTER会触发action事件。从JavaFX 8开始,< code >按钮的行为似乎发生了变化。下面是< code > com . sun . Java FX . scene . control . behavior . button behavior 的不同实现,显示了注册的键绑定。
JavaFX 8u202
protected static final List<KeyBinding> BUTTON_BINDINGS = new ArrayList<KeyBinding>();
static {
BUTTON_BINDINGS.add(new KeyBinding(SPACE, KEY_PRESSED, PRESS_ACTION));
BUTTON_BINDINGS.add(new KeyBinding(SPACE, KEY_RELEASED, RELEASE_ACTION));
}
JavaFX 11.0.2
public ButtonBehavior(C control) {
super(control);
/* SOME CODE OMITTED FOR BREVITY */
// then button-specific mappings for key and mouse input
addDefaultMapping(buttonInputMap,
new KeyMapping(SPACE, KeyEvent.KEY_PRESSED, this::keyPressed),
new KeyMapping(SPACE, KeyEvent.KEY_RELEASED, this::keyReleased),
new MouseMapping(MouseEvent.MOUSE_PRESSED, this::mousePressed),
new MouseMapping(MouseEvent.MOUSE_RELEASED, this::mouseReleased),
new MouseMapping(MouseEvent.MOUSE_ENTERED, this::mouseEntered),
new MouseMapping(MouseEvent.MOUSE_EXITED, this::mouseExited),
// on non-Mac OS platforms, we support pressing the ENTER key to activate the button
new KeyMapping(new KeyBinding(ENTER, KeyEvent.KEY_PRESSED), this::keyPressed, event -> PlatformUtil.isMac()),
new KeyMapping(new KeyBinding(ENTER, KeyEvent.KEY_RELEASED), this::keyReleased, event -> PlatformUtil.isMac())
);
/* SOME CODE OMITTED FOR BREVITY */
}
如您所见,两者都注册SPACE以在按钮
具有焦点时触发它。但是,JavaFX 11.0.2 实现也为相同的平台注册 ENTER,但仅适用于非 Mac OS 平台。我找不到有关此行为更改的任何文档。
如果您希望JavaFX 8具有相同的行为,并且不介意深入JavaFX的内部,那么您可以使用反射来改变应用程序中所有类似按钮的控件的行为。下面是一个实用方法示例:
import com.sun.javafx.PlatformUtil;
import com.sun.javafx.scene.control.behavior.ButtonBehavior;
import com.sun.javafx.scene.control.behavior.KeyBinding;
import java.lang.reflect.Field;
import java.util.List;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
public final class ButtonUtils {
public static void installEnterFiresButtonFix() throws ReflectiveOperationException {
if (PlatformUtil.isMac()) {
return;
}
Field bindingsField = ButtonBehavior.class.getDeclaredField("BUTTON_BINDINGS");
Field pressedActionField = ButtonBehavior.class.getDeclaredField("PRESS_ACTION");
Field releasedActionField = ButtonBehavior.class.getDeclaredField("RELEASE_ACTION");
bindingsField.setAccessible(true);
pressedActionField.setAccessible(true);
releasedActionField.setAccessible(true);
@SuppressWarnings("unchecked")
List<KeyBinding> bindings = (List<KeyBinding>) bindingsField.get(null);
String pressedAction = (String) pressedActionField.get(null);
String releasedAction = (String) releasedActionField.get(null);
bindings.add(new KeyBinding(KeyCode.ENTER, KeyEvent.KEY_PRESSED, pressedAction));
bindings.add(new KeyBinding(KeyCode.ENTER, KeyEvent.KEY_RELEASED, releasedAction));
}
private ButtonUtils() {}
}
您应该在应用程序启动的早期,在创建任何< code >按钮之前调用此实用工具方法。下面是一个使用它的例子:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
ButtonUtils.installEnterFiresButtonFix();
} catch (ReflectiveOperationException ex) {
ex.printStackTrace();
}
Button button = new Button("Save");
button.setOnAction(event -> {
event.consume();
System.out.println(new FileChooser().showSaveDialog(primaryStage));
});
Scene scene = new Scene(new StackPane(button), 300, 150);
primaryStage.setScene(scene);
primaryStage.setTitle("Workshop");
primaryStage.show();
}
}
提醒:此修复依赖于实现。
AccessibilityService在系统的内存管理方面与普通服务有何不同? 我想问的是:系统可以为了节省内存而关闭AccessibilityService吗?如果可以,当您进入AccessibilityService时,您会看到它打开还是关闭?用户是否必须再次手动打开? 使用startForeground是否有助于使AccessibilityService保持活动状态? 在一个类似的问题中,
我想拆分我的验证器的声明和实现,与Spring boot环境中的这个问题非常相似。看起来好像是我让它几乎起作用了。我看到我的验证器实际上是由Spring验证调用的,但在执行验证后,Hibernate会抛出一个异常: 这是因为是一个接口(如预期)。 我已经这样配置了Spring(这是一个不同问题的答案): 我的自定义验证器: 所以它试图通过验证器名称找到一个Spring bean。所以我有一个验证器
目前,不允许在接口中使用get/set方法(访问器)。例如: 此外,TypeScript 不允许在类方法中使用数组函数表达式:例如: 有没有其他方法可以在接口定义上使用getter和setter?
问题内容: 我正在尝试使用jQuery在特定端口上运行AJAX查询: 这不起作用:没有进行AJAX调用,并且Firebug中没有任何异常。如果我不指定端口,它确实可以工作。有人知道为什么吗? 问题答案: 由于“ 同源来源”政策而无法使用。仅在相同的域,协议和端口中才允许AJAX请求。 如果您确实需要从该来源获取数据,则应该期待JSONP。
是否可以在 SQL SERVER 中的事务中使用 SELECT 语句锁定行?我想锁定该行,以便外部的其他事务无法访问该行。 提交或回滚事务后,应释放该行。这就是我的意思。。。 有人有建议吗?我应该执行 UPDATE 语句来锁定该行吗? 请不要将此问题标记为重复问题。因为,我不是在问UPDATE语句,而是在问SELECT 编辑:我试图“设置事务隔离级别串行化”,但这锁定了太多东西。我的SP很大,它有
问题内容: 我不确定如何更清楚地表达我的问题。基本上,PyPlot是否限于一个实例/窗口?我尝试的任何破解或变通办法要么导致程序冻结,要么使第二个pyplot窗口排队,直到第一个关闭。 问题答案: 当然,只需打开一个新图即可: 如果您在默认的python解释器中运行此命令,则此命令将无效,因为每个图形都需要输入gui的mainloop。如果要在交互式shell中运行事物,请查看IPython。但是