我正在尝试在行和列中显示字符串。由于它们的长度不同,并且代表连续文本的一部分,因此我希望每个组件仅占用显示整个String所需的大小。
到目前为止,我设法将单个项目加载到列表中,限制行数并使它们水平包装。我现在写了一个自定义ListCellRenderer,因为我认为这可以解决我的问题,但是它并没有达到我希望的方式。属于每个项目的两个字符串既不居中也不显示在彼此上方(实际上,它们根本不可读,因为它们似乎是在单元格外部绘制的),并且它们都具有相同的大小。我在做什么错了?
这是我的渲染器的外观:
public class ElementRenderer extends JPanel implements ListCellRenderer<Element> {
private Element element;
@Override
public Component getListCellRendererComponent(JList<? extends Element> list, Element value, int index,
boolean isSelected, boolean cellHasFocus) {
element = (Element) value;
if (element.getTag().equals("N/A"))
setEnabled(false);
else
setEnabled(true);
if (isSelected)
setBorder(BorderFactory.createLoweredSoftBevelBorder());
else
setBorder(BorderFactory.createRaisedSoftBevelBorder());
return this;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (!isEnabled())
setBackground(Color.GRAY);
String word = element.getWord();
String tag = element.getTag();
FontMetrics fm = getFontMetrics(DataManager.getCurrentFont());
Rectangle bounds = getVisibleRect();
int y = bounds.y + ((bounds.height - 2*fm.getHeight())/2) + fm.getAscent();
g.drawString(word, bounds.x + (bounds.width - fm.stringWidth(word))/2, y);
g.drawString(tag, bounds.x + (bounds.width - fm.stringWidth(tag))/2, y + fm.getHeight());
}
@Override
public Dimension getPreferredSize() {
FontMetrics fm = getFontMetrics(DataManager.getCurrentFont());
int wordwidth = fm.stringWidth(element.getWord());
int tagwidth = fm.stringWidth(element.getTag());
if (tagwidth > wordwidth)
wordwidth = tagwidth;
return new Dimension(17+wordwidth, 3+fm.getHeight()*2);
}
答案 0 :(得分:1)
在不弄乱JList
的{{1}}或LayoutManager
的情况下,我能找到的最简单的解决方案的确是创建自定义ListUI
,但使用以下逻辑:
ListCellRenderer
是其中包含ListCellRenderer
的{{1}}。JPanel
作为DefaultListCellRenderer
,将填满整个单元格空间。ListCellRenderer
将位于我们的自定义JPanel
中。我们可以通过将DefaultListCellRenderer
中的ListCellRenderer
设置为LayoutManager
来实现。由于将仅添加单个组件(即JPanel
是GridBagLayout
),因此它将居中。遵循示例代码:
DefaultListCellRenderer
以及示例屏幕截图(具有选定的元素):