我正在编写一个自定义的JComponent,对于不同的外观应具有不同的外观。我打算至少对ComponentUiWindowsLookAndFeelMetalLookAndFeel使用不同的MotifLookAndFeel类。

现在,尽管此任务似乎很容易,但我无法找到如何通过自定义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-但这不是我想要的。

最佳答案

如果您想要/不想要-您必须以某种方式向UIManager注册自定义UI,它又如何知道它们;-)

不过,您不需要的是受支持的LAF的自定义子类:您可以手动注册它们(并在LAF更改时更新注册,也就是说,您需要在UIManager上有一个PropertyChangeListener,以便在此类中进行通知一个案例)。

假设JCustom的类ID为“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

07-25 22:22
查看更多