【问题标题】:Netbeans OptionsPanelController buttons focusNetbeans OptionsPanelController 按钮焦点
【发布时间】:2016-08-22 07:39:54
【问题描述】:

我使用的是netbeans平台的OptionsPanelController

来自https://platform.netbeans.org/tutorials/nbm-options.html本教程。

我的问题是, 通过使用此面板,Ok button 默认获得焦点。

我怎样才能让它默认不集中。

注意:

由于它是一个 netbeans 平台应用程序,我从 Netbeans IDE 打开了Tools->Options ,在该对话框中,默认情况下,“确定”按钮也是焦点。

【问题讨论】:

    标签: java netbeans


    【解决方案1】:

    在 netbeans 源代码中的私有包和最终类中,这种行为是硬编码的,因此可以完成,但需要修改 netbeans 源代码并更改代码以依赖于您自己的版本netbeans,或使用反射或 java 字节码注入来覆盖现有行为。

    您需要修改的感兴趣的类是: org.netbeans.api.options.OptionsDisplyer 和 org.netbeans.api.options.OptionsDisplayerImpl

    更具体地说,OptionsDialogImpl.showOptionsDialog(...) 方法创建一个 DialogDisplayer 对象,该对象的默认选定值设置为 DialogDescriptor.OK_OPTION,这会导致无论何时打开 Tools->Options 窗口都会选择 OK 按钮。

    您唯一的解决方法/技巧是: 选项 1)构建您自己的 netbeans 版本,将硬编码行为更改为您需要的。您将需要从源代码 netbeans 克隆和构建;请参阅以下网址提供的说明:http://wiki.netbeans.org/WorkingWithNetBeansSources#Try_NetBeans_buildSimply

    签出/克隆源代码后,您需要在 OptionsDisplayerImpl.java 中的第 204 行附近进行编辑,用您喜欢的按钮(例如 DialogDescriptor.CANCEL_OPTION)替换输入参数 DialogDescriptor.OK_OPTION。您需要编辑的行如下所示。

    descriptor = new DialogDescriptor(optionsPanel,title,modal,options,DialogDescriptor.OK_OPTION,DialogDescriptor.DEFAULT_ALIGN, null, null, false);
    

    选项 2) 使用 java 反射执行一些黑魔法,以访问和更改默认选定按钮的值,或用您的自定义实现替换私有字段,覆盖默认行为。

    示例代码:

    OptionsDisplayer displayer = OptionsDisplayer.getDefault();        
        Object impl = getField(displayer, "impl"); 
        if(impl != null){
            WeakReference<DialogDescriptor> descriptorRef = (WeakReference<DialogDescriptor>)getField(impl, "descriptorRef");
            if(descriptorRef != null){                
                DialogDescriptor descriptor = descriptorRef.get();
                //change default initial selected butten from "OK" to "CANCEL"
                descriptor.setValue(DialogDescriptor.CANCEL_OPTION); //change default initial selected butten from "OK" to "CANCEL"
            }
        }
    
    /**
     * Java reflection utility method to get the Object for a given field regardless of whether it is private or not, by it's given field name.
     * @param obj The Object that contains the desired field.
     * @param fieldName The name of the field
     * @return The Object with the given fieldName found in Object 'obj'. Returns null if no such field exists.
     */
    public static Object getField(Object obj, String fieldName) {
        Class tmpClass = obj.getClass();
        do {
            try {
                Field f = tmpClass.getDeclaredField(fieldName);
                if(f != null){
                    f.setAccessible(true);
                    return f.get(obj);
                }                
            } catch (NoSuchFieldException e) {
                tmpClass = tmpClass.getSuperclass();
            } catch (IllegalArgumentException | IllegalAccessException ex) {
                ex.printStackTrace();
                return null;
            }
        } while (tmpClass != null);
        return null; //null if not found
    }
    

    选项3)更多java black-magic,在cl​​assloader处拦截字节码加载,在加载到JVM之前修改。例如使用字节码操作库,例如 AspectJ、Javassist、ASM 或 CGLib

    【讨论】:

    • 我尝试了 Option:2 并且您的示例代码几乎没有更改,我能够转移焦点..
    猜你喜欢
    • 1970-01-01
    • 2016-11-11
    • 2011-11-27
    • 2011-04-22
    • 2015-07-05
    • 2011-02-22
    • 2016-08-15
    • 1970-01-01
    • 2011-06-29
    相关资源
    最近更新 更多