我正在编写一个使用本地系统外观的 Java 应用程序。在程序中有一个 ListCellRenderer,它呈现一个彩色点(自定义 JComponment),后跟一些给定对象的文本。这在使用 Swing 的默认 Metal 外观和感觉时效果很好。
但是,当我使用 Windows 外观时,单元格在下拉列表中正确呈现,但所选项目(当用户未选择其他选项时显示的项目)仅呈现文本和忽略彩色点。如果我更改渲染器以设置字体,则在下拉菜单和所选项目中都会观察到正确的字体,因此我知道至少部分使用了单元格渲染器。
我在网上阅读了一些关于导致此类问题的不同 LAF 的帖子,但没有遇到任何讨论我的特定问题的人。
如果有人好奇,这里是代码:
.
@Override
public Component getListCellRendererComponent(JList<? extends ColoredDisplayable> jlist, ColoredDisplayable e, int i, boolean isSelected, boolean hasFocus) {
JPanel cell = new JPanel(new GridBagLayout());
cell.setOpaque(false);
JLabel label = new JLabel(e.getDisplayString());
label.setOpaque(false);
label.setBorder(BorderFactory.createEmptyBorder(1, 4, 1, 4));
label.setHorizontalAlignment(JLabel.LEFT);
Color deselectedBackground = cell.getBackground();
Color deselectedTextColor = cell.getForeground();
// LAYOUT COMPONENTS
// Dot
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = INSETS;
gbc.anchor = GridBagConstraints.LINE_START;
gbc.weightx = 0.0f;
gbc.fill = GridBagConstraints.NONE;
cell.add(new Dot(e.getColor()), gbc);
// Label
gbc.gridx = 1;
gbc.weightx = 1.0f;
gbc.fill = GridBagConstraints.HORIZONTAL;
cell.add(label, gbc);
if (isSelected){
cell.setOpaque(true);
cell.setBackground(MetalLookAndFeel.getTextHighlightColor());
} else {
cell.setBackground(deselectedBackground);
cell.setForeground(deselectedTextColor);
}
return cell;
}
此外,这是自定义组件的代码,任何人都想尝试一下,看看我是否只是在这里做一些愚蠢的事情:
public class Dot extends JComponent {
/** The size of the dot. */
private static final int SIZE = 10;
/** The size of the dot. */
private static final int PAD = 4;
private static final Dimension DIM = new Dimension(SIZE + PAD, SIZE + PAD);
/** The Color to render the dot. */
private final Color m_color;
/** The Dot itself. */
private static final Ellipse2D.Double DOT = new Ellipse2D.Double(PAD / 2, PAD / 2, SIZE, SIZE);
/**
* Creates a dot of the specified color.
* @param color the color to make the dot.
*/
public Dot(Color color) {
m_color = color;
}
@Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(m_color);
g2d.fill(DOT);
}
@Override
public Dimension getPreferredSize() {
return DIM;
}
}
编辑: 我刚刚在 Ubuntu 12.04 上对此进行了测试,并且单元格渲染器在那里按预期工作(尽管 JCombobox 没有像没有应用自定义渲染器时那样渲染其外部边框)。
编辑:随着我越来越多地对此进行研究,似乎 JComboBox 上的 setEditor 方法可能存在某些问题,但是当不可编辑时,渲染器应用作方法状态的 javadoc:
设置用于在 JComboBox 字段中绘制和编辑所选项目的编辑器。仅当接收 JComboBox 是可编辑的时才使用编辑器。如果不可编辑,组合框将使用渲染器来绘制所选项目。
这似乎不是我所看到的行为。为了让 Windows LAF 的用户观察到我的单元格渲染器的所有部分,我必须做什么?