【问题标题】:Extending existing Swing look and feels with custom JComponents使用自定义 JComponent 扩展现有 Swing 外观
【发布时间】:2014-06-06 11:29:26
【问题描述】:

我正在编写一个自定义 JComponent,对于不同的外观和感觉应该看起来不同。我打算至少为WindowsLookAndFeelMetalLookAndFeelMotifLookAndFeel 设置不同的ComponentUi 类。

现在,虽然这项任务看起来很简单,但我不知道如何使用我的自定义 ComponentUi 类轻松扩展现有外观。

如何注册正确的ComponentUi 以获得不同的外观和感觉?这可能吗?如果不是,为不同的外观和感觉编写自定义组件的首选方法是什么?


更具体地说,目前我在自定义组件中覆盖 JComponent#updateUI 以设置不同的 ComponentUi 实例:

@Override
public void updateUI() {
    LookAndFeel feel = UIManager.getLookAndFeel();
    if (feel instanceof WindowsLookAndFeel) {
        setUI(MyWindowsCustomUi.createUI(this));
    } else if (feel instanceof MotifLookAndFeel) {
        setUI(MyMotivCustomUi.createUI(this));
    } else if (feel instanceof MetalLookAndFeel) {
        setUI(MyMetalCustomUi.createUI(this));
    } else{
        setUI(MyBasicCustomUi.createUI(this));
    }
}

但这种方法似乎完全违背了外观和感觉的目的和实用性。我希望能够将其更改为以下内容:

public void updateUI() {
    setUI((MyCustomUi)UIManager.getUI(this));
}

这应该为当前的外观设置MyCustomUi 的正确子类。

我知道,我可以通过创建每个支持的LookAndFeel 的自定义子类来轻松实现这一点,这些子类在例如注册相应的ComponentUi BasicLookAndFeel#initComponentDefaults(UIDefaults) - 但这不是我想做的。

【问题讨论】:

    标签: java swing custom-component look-and-feel uimanager


    【解决方案1】:

    无论你是否愿意 - 你必须以某种方式向 UIManager 注册你的自定义 UI,它怎么会知道它们 ;-)

    不过,您不需要的是受支持 LAF 的自定义子类:您可以手动注册它们(并在 LAF 更改时更新注册,也就是说,您需要 UIManager 上的 propertyChangeListener在这种情况下通知)。

    假设 JCustom 的 classID 为“CustomUI”且 ui 实现遵循通常的约定(即 BasicCustomUI、WindowsCustomUI ...),注册将类似于:

     String prefix = UIManager.getLookAndFeel().getID();
     UIManager.getLookAndFeelDefaults().put("CustomUI", myUIPackage + "." + prefix + CustomUI);
    

    请注意,自定义 ui 需要一个静态的 createUI,它返回 ui 的一个实例:

     public static ComponentUI createUI(JComponent comp) {
         return new BasicCustomUI(); 
     }
    

    并且组件需要发布它的uiClassID,查找并设置它的ui:

    @Override
    public String getUIClassID() {
        return "CustomUI";
    }
    
    @Override
    public void updateUI() {
        setUI(UIManager.getUI(this));
    }
    

    使用 SwingX 的好处是提供了自动注册自定义组件的基础设施。您将需要一个额外的类 - CustomAddon - 它提供每个 LAF 配置,并且自定义组件必须贡献该插件:

    // in JCustom
    
    static {
        LookAndFeelAddons.contribute(new CustomAddon());
    }
    
    // in CustomAddon
    
    @Override
    protected void addBasicDefaults(LookAndFeelAddons addon, DefaultsList defaults) {
        super.addBasicDefaults(addon, defaults);
        defaults.add("CustomUI",
                "mypackage.BasicCustomUI");
    }
    
    @Override
    protected void addMacDefaults(LookAndFeelAddons addon, DefaultsList defaults) {
        super.addMacDefaults(addon, defaults);
        defaults.add("CustomUI",
                "mypackage.MacCustomUI");
    }
    
    //... similar methods for all supported LAFs
    

    【讨论】:

    • 非常感谢 - 我使用来自 SwingX 的 LookAndFeelAddons.contribute() 注册了自定义组件,它就像一个魅力。
    猜你喜欢
    • 2012-11-01
    • 2011-03-10
    • 1970-01-01
    • 2020-02-25
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多