我正在使用Synth作为UI的项目,并希望实现一些自定义按钮。按钮需要使用合成XML设置文件中的样式设置 - 例如不同状态(MOUSE_OVER,PRESSED等)的字体颜色不同。
我坚持的问题是某些按钮需要有额外的子组件 - 例如有些需要不止一个标签。我希望子组件选择与标准按钮子组件相同的样式设置。
我觉得我应该只能扩展JButton
并覆盖/扩展paintComponent
来调用某些子组件的draw方法。我对这种方法的一些方面有点不确定:例如要传递给paintComponent
的参数;以及如何确保子组件获得正确的Synth样式设置(特别是状态)。
撇开:我尝试延长JPanel
,但在使用这种方法时遇到了一些困难(请参阅此处:JPanel states for Synth)。
编辑:所以,我发现可以在按钮中添加子组件并让它们正确渲染。即使JButton.getLayout()
返回null,按钮也会使用OverlayLayout
,除非您调用JButton.setLayout()
。调用JButton.setLayout(null)
会阻止使用OverlayLayout,这就是我处理布局的方式。
我正在研究几种不同的方法来更新子控件的样式,稍后会报告这些。
答案 0 :(得分:1)
所以,如果它对其他任何人有用,我最后采用的方法是:
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)似乎是最好的。
还有trashgod建议实现自定义UI委托(扩展BasicButtonUI
)的方法,但如果你采取这种方式,我认为你将不得不重新实现SynthButtonUI的大部分。