3

我正在写一个 custom JComponent,对于不同的外观和感觉应该看起来不同。我打算ComponentUi至少为WindowsLookAndFeelMetalLookAndFeelMotifLookAndFeel.

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注册相应的- 但这不是我想要做的。ComponentUiBasicLookAndFeel#initComponentDefaults(UIDefaults)

4

1 回答 1

5

如果你想要它 - 你必须以某种方式向 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 需要一个返回 ui 实例的静态 createUI:

 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
于 2014-04-22T08:55:51.883 回答