Swing -自定义按钮w/Synth



我正在研究一个使用Synth作为UI的项目,并希望实现一些自定义按钮。按钮需要使用synth XML设置文件中的样式设置-例如,不同状态(MOUSE_OVER, PRESSED等)的字体颜色不同。

我卡住的问题是,一些按钮需要有额外的子组件-例如,一些需要多个标签。我希望这些子组件与标准按钮子组件具有相同的样式设置。

我觉得我应该能够扩展JButton和覆盖/扩展paintComponent调用一些子组件的绘制方法。我对这种方法的几个方面有点不确定:例如,传递给paintComponent的参数;以及如何确保子组件获得正确的Synth样式设置(特别是wrt)。美国)。

题外话:我曾尝试扩展JPanel,但在使用这种方法时遇到了一些困难(参见这里:Synth的JPanel状态)。

EDIT:所以,我发现有可能将子组件添加到按钮并使它们正确呈现。似乎即使JButton.getLayout()返回null,按钮将使用OverlayLayout,除非您调用JButton.setLayout()。调用JButton.setLayout(null)确实防止OverlayLayout被使用,所以这就是我如何处理布局。

我正在研究几种不同的方法来更新子控件的样式,稍后会报告。

所以,如果它对其他人有用的话,这是我最后采用的方法:

class CustomButton extends JButton {
    CustomButton() {
        // ... normal button init
        // Enable absolute positioning of sub-components.
        setLayout(null);
        updateStyles();
        getModel().addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                updateStyles();
            }
        });
    }
    private void updateStyles() {
        // See below for implementation.
    }
    private int getSynthComponentState() {
        // This is basically a copy of SynthButtonUI.getComponentState(JComponent)
        int state = SynthConstants.ENABLED;
        if (!isEnabled()) {
            state = SynthConstants.DISABLED;
        }
        if (model.isPressed()) {
            if (model.isArmed()) {
                state = SynthConstants.PRESSED;
            } else {
                state = SynthConstants.MOUSE_OVER;
            }
        }
        if (model.isRollover()) {
            state |= SynthConstants.MOUSE_OVER;
        }
        if (model.isSelected()) {
            state |= SynthConstants.SELECTED;
        }
        if (isFocusOwner() && isFocusPainted()) {
            state |= SynthConstants.FOCUSED;
        }
        if (isDefaultButton()) {
            state |= SynthConstants.DEFAULT;
        }
        return state;
    }
}

我发现了如何实现updateStyles()方法的两种方法:(A)更改组件的名称以使用不同的命名样式,或者(B)将样式设置从按钮复制到子组件。方法(A)非常简单,方法(B)的工作原理如下:

private void updateStyles() {
    SynthStyle ss = SynthLookAndFeel.getStyle(this, Region.BUTTON);
    SynthContext sc = new SynthContext(this, Region.BUTTON, ss, getSynthComponentState());
    for (Component c : getComponents()) {
        c.setFont(ss.getFont(sc));
        c.setBackground(ss.getColor(sc, ColorType.BACKGROUND));
        c.setForeground(ss.getColor(sc, ColorType.FOREGROUND));
        // ... and so on if you have other style elements to be changed.
    }
}
如果您为每个不同的状态更改多个样式设置,方法(A)可能更好,尽管如果您为许多不同的状态使用不同的样式,它可能会变得笨拙。如果你只改变几个样式设置(例如,在我的情况下,我只关心颜色,至少现在),那么方法(B)似乎是最好的。

也有建议的方法由垃圾神实现自定义UI委托(扩展BasicButtonUI),但如果你采取这条路线,我认为你将不得不重新实现SynthButtonUI的大部分

最新更新