JavaFX 2 - 设置defaultButton属性:互斥? [英] JavaFX 2 -- Setting the defaultButton property: mutually exclusive?

查看:166
本文介绍了JavaFX 2 - 设置defaultButton属性:互斥?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Visual Basic 6中,如果将窗体按钮控件的DefaultButton属性设置为true,则表单中所有其他按钮控件上的相同属性设置为false,即属性是互斥的(如单选按钮) )。

In Visual Basic 6, if you set the DefaultButton property of a form button control to true, the same property on all the other button controls in the form was set to false, i.e. the property was mutually exclusive (like a radio button).

我在GUI上遇到的行为似乎表明JavaFX中的多个按钮可能将defaultButton属性设置为true,并且有多个按钮将从系统接收VK_Enter按钮事件。

I am getting behavior on my GUI that seems to indicate that more than one button in JavaFX may have the defaultButton property set to true, and that more than one button will receive VK_Enter button events from the system.

setDefaultButton()方法和defaultButton属性的JavaFX 2.2文档没有说明此问题。

The JavaFX 2.2 documentation for the setDefaultButton() method and defaultButton property does not clarify this issue.

我有一个带有一堆控件的AnchorPanel和另一个带有一组独立控件的AnchorPanel。这些显示在同一个舞台上,哪一个是setVisible(true)给用户取决于他正在使用的信息。

I have one AnchorPanel with a bunch of controls and another with a separate bunch of controls. These are shown on the same stage, and which one is setVisible(true) to the user depends on what information he's working with.

我想知道我是否需要迭代我的活动窗格上的按钮控件并在我尝试将其设置为true之前将所有这些属性的defaultButton属性设置为false,以避免因多个按钮接收Enter键事件而导致的奇怪行为。

I'm wondering if I need to iterate through the button controls on my active panes and set the defaultButton property to false for all of them before I try to set one to true in order to avoid odd behavior resulting from more than one button receiving Enter Key events.

编辑05/05/2013 - 这是我的ChangeListener代码。我最初把它写成一个匿名的内部类,我直接附加到TextField控件txtDx的focusedProperty。但是,我想也许我可以通过在我不希望它被触发的那些时间(即,当它的窗格是不可见或禁用时)移除监听器来修复我的错误。所以我将Listener移动到一个内部类,并通过实例变量引用它的实例。有了引用,我可以根据显示的窗格添加和删除Listener。

EDIT 05/05/2013 -- Here is the ChangeListener code I have. I had originally written it as an anonymous inner class that I was attaching directly to the focusedProperty of the TextField control txtDx. However, I thought that maybe I could fix my error by removing the Listener during those times when I didn't want it firing (i.e., when its pane was invisitble or disabled). So I moved the Listener to an inner class and have an instance of it referenced to by an instance variable. Having the reference allows me to add and remove the Listener depending on which pane is displayed.

无论如何,这里是Listener类:

Anyway, here is the Listener class:

private class FocusPropertyChangeListener implements ChangeListener<Boolean> {

    FocusPropertyChangeListener() { System.out.println("New FPCL instance"); }

    @Override
    public void changed(ObservableValue<? extends Boolean> ov, 
        Boolean oldb, Boolean newb) {
        System.out.println("Focus change triggered");

        if (ancEncEditor.isVisible() && !ancEncEditor.isDisabled()) {
            boolean b = (newb != null && newb.booleanValue() == true);
            System.out.println("txtDx focus change event triggered: DxAdd = " + b);

            btnWindowCommit.setDefaultButton(!b);
            btnWindowClose.setCancelButton(true);
            btnDxAdd.setDefaultButton(b);
        }
    }
}

正如您所见,事件处理程序我对setDefaultButton进行了两次(可能是并发的)调用。如果我在txtDx中编辑,则意图是使用btnDxAdd,否则使用btnWindowCommit。我将尝试摆脱对setDefaultButton的大概不需要的调用,看看我是否仍然得到ConcurrentModificationExceptions。

As you can see, in the event handler I make two (presumably concurrent) calls to setDefaultButton. The intent is to use btnDxAdd if I am editing in txtDx, otherwise use btnWindowCommit. I'll try getting rid of the presumably unneeded calls to setDefaultButton and see if I still get ConcurrentModificationExceptions.

编辑05/05/2013 - 添加堆栈跟踪。这里...

EDIT 05/05/2013 -- Adding the stack trace. Here goes...

java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:894)
at java.util.HashMap$EntryIterator.next(HashMap.java:934)
at java.util.HashMap$EntryIterator.next(HashMap.java:932)
at com.sun.javafx.collections.ObservableMapWrapper$ObservableEntrySet$1.next(ObservableMapWrapper.java:560)
at com.sun.javafx.collections.ObservableMapWrapper$ObservableEntrySet$1.next(ObservableMapWrapper.java:548)
at com.sun.javafx.scene.KeyboardShortcutsHandler.processAccelerators(KeyboardShortcutsHandler.java:286)
at com.sun.javafx.scene.KeyboardShortcutsHandler.dispatchBubblingEvent(KeyboardShortcutsHandler.java:119)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:28)
at javafx.event.Event.fireEvent(Event.java:171)
at javafx.scene.Scene$KeyHandler.process(Scene.java:3513)
at javafx.scene.Scene$KeyHandler.access$2300(Scene.java:3472)
at javafx.scene.Scene.impl_processKeyEvent(Scene.java:1904)
at javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2270)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:136)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:100)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(GlassViewEventHandler.java:163)
at com.sun.glass.ui.View.handleKeyEvent(View.java:518)
at com.sun.glass.ui.View.notifyKey(View.java:951)
at com.sun.glass.ui.win.WinApplication._enterNestedEventLoop(Native Method)
at com.sun.glass.ui.Application.enterNestedEventLoop(Application.java:383)
at com.sun.glass.ui.EventLoop.enter(EventLoop.java:83)
at com.sun.javafx.tk.quantum.QuantumToolkit.enterNestedEventLoop(QuantumToolkit.java:520)
at javafx.stage.Stage.showAndWait(Stage.java:397)
at org.kls.md.censusassistant.DialogController.showAndWait(DialogController.java:94)
at org.kls.md.censusassistant.DCMainEditor.handleEncDetails(DCMainEditor.java:287)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:75)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:279)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1435)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:28)
at javafx.event.Event.fireEvent(Event.java:171)
at javafx.scene.Node.fireEvent(Node.java:6863)
at javafx.scene.control.Button.fire(Button.java:179)
at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:193)
at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:336)
at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:329)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:64)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:33)
at javafx.event.Event.fireEvent(Event.java:171)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3328)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3168)
at javafx.scene.Scene$MouseHandler.access$1900(Scene.java:3123)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1563)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2265)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:250)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:173)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:292)
at com.sun.glass.ui.View.handleMouseEvent(View.java:528)
at com.sun.glass.ui.View.notifyMouse(View.java:922)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29)
at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:73)
at java.lang.Thread.run(Thread.java:722)

编辑05/05/2013 - 我改变了我的代码,以便我不再清除defaultButton的前设置,即只调用一次setDefaultButton(true)。我的想法是,由于支持代码使用Runnable执行此操作,因此 - 这是我得到的ConcurrentModificationExceptions的原因。

EDIT 05/05/2013 -- I altered my code so that I would no longer be clearing former settings of defaultButton, i.e. just one call to setDefaultButton(true). The idea was that since the backing code performs this operation using a Runnable, -perhaps- this was the cause of the ConcurrentModificationExceptions I was getting.

所以,现在它确实出现了事实上,当我尝试在btnDxAdd和btnWindowCommit之间进行默认按钮更改时,我无法再在代码中触发ConcurrentModificationExceptions。

So, now it does appear that in fact I am no longer able to trigger ConcurrentModificationExceptions in my code when I attempt to change between btnDxAdd and btnWindowCommit as the default button.

但是......

我也无法获得我想要的行为。当我现在在txtDx控件中编辑时,我可以整天按Enter键,按钮不会触发。我已经确认我的focusProperty ChangeListener被激活,并且对txtDx.setDefaultButton(true)进行了一次调用。无论如何,我无法得到我想要的行为。

I am also no longer able to get the behavior I want. When I am editing in the txtDx control now, I can press the Enter key all day and the button will not fire. I have confirmed that my focusProperty ChangeListener fired and that a single call to txtDx.setDefaultButton(true) was made. Regardless, I am not able to get the behavior I want.

推荐答案

关于javadoc澄清的错误:javafx-jira.kenai.com / browse / RT-30200

Bug about javadoc clarification : javafx-jira.kenai.com/browse/RT-30200

有关实施的错误: https://javafx-jira.kenai.com/browse/RT-30206

我观察了皮肤类的代码,这是可观察的来自OpenJFX:

I watched code from skin class, which is observable from OpenJFX:

当你setDefault(true / false)时发生了什么:

What is happening, when you setDefault(true/false):

Runnable defaultButtonRunnable = new Runnable() {
        public void run() {
            if (!getSkinnable().isDisabled()) {
                getSkinnable().fire();
            }
        }
    };

private void setDefaultButton(boolean value) {

    KeyCode acceleratorCode = KeyCode.ENTER;
    defaultAcceleratorKeyCodeCombination = 
            new KeyCodeCombination(acceleratorCode);

    if (! value) {
        /*
        ** first check of there's a default button already
        */
        Runnable oldDefault = getSkinnable().getParent().getScene().getAccelerators().get(defaultAcceleratorKeyCodeCombination);
        if (!defaultButtonRunnable.equals(oldDefault)) {
            /*
            ** is it us?
            */
            getSkinnable().getParent().getScene().getAccelerators().remove(defaultAcceleratorKeyCodeCombination);
        }
    }
    getSkinnable().getParent().getScene().getAccelerators().put(defaultAcceleratorKeyCodeCombination, defaultButtonRunnable);
}

工作原理:当您将新按钮设为默认按钮时,它会找到现有按钮默认按钮,并从存储在场景的acelerators列表中按下ENTER键上的acelerator。并将其自身添加为默认按钮。所以你不需要在其他按钮上设置默认值。

How it works : when you set new button as default, it finds the existing default button, and removes acelerator on ENTER key press from acelerators list stored at scene. And adds itself as a default button. So you don't need to setDefault on other buttons.

这篇关于JavaFX 2 - 设置defaultButton属性:互斥?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆