Расширение существующего внешнего вида Swing с помощью пользовательских JComponents

Я пишу пользовательский JComponent, который должен выглядеть по-разному для разных видов и ощущений. Я намерен иметь разные классы ComponentUi по крайней мере для WindowsLookAndFeel, MetalLookAndFeel и для 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, например, во время. BasicLookAndFeel#initComponentDefaults(UIDefaults) - но это не то, чем я хочу заниматься.


person Balder    schedule 22.04.2014    source источник


Ответы (1)


Хотите вы этого или нет - вы должны каким-то образом зарегистрировать свои пользовательские интерфейсы в UIManager, иначе как он мог узнать о них ;-)

Что вам не нужно, так это настраиваемый подкласс поддерживаемых LAF: вы можете зарегистрировать их вручную (и обновить регистрацию при изменении LAF, то есть вам понадобится свойствоChangeListener в UIManager для получения уведомлений в таких случаях). случай).

Предполагая, что JCustom с classID "CustomUI" и реализации пользовательского интерфейса, следующие обычным соглашениям (то есть BasicCustomUI, WindowsCustomUI...), регистрация будет выглядеть примерно так:

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

Обратите внимание, что пользовательскому пользовательскому интерфейсу требуется статический createUI, который возвращает экземпляр пользовательского интерфейса:

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

и компонент должен опубликовать свой uiClassID, выполнить поиск и установить свой пользовательский интерфейс:

@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
person kleopatra    schedule 22.04.2014
comment
Большое спасибо - я зарегистрировал пользовательский компонент, используя LookAndFeelAddons.contribute() из SwingX, и он работает как шарм. - person Balder; 22.04.2014