有没有办法使JList的每个项目都具有不同的宽度?

时间:2019-06-20 11:10:44

标签: java swing jlist paintcomponent renderer

我正在尝试在行和列中显示字符串。由于它们的长度不同,并且代表连续文本的一部分,因此我希望每个组件仅占用显示整个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);
    }

1 个答案:

答案 0 :(得分:1)

在不弄乱JList的{​​{1}}或LayoutManager的情况下,我能找到的最简单的解决方案的确是创建自定义ListUI,但使用以下逻辑:

  • 自定义ListCellRenderer是其中包含ListCellRenderer的{​​{1}}。
  • 自定义JPanel作为DefaultListCellRenderer,将填满整个单元格空间。
  • ListCellRenderer将位于我们的自定义JPanel中。我们可以通过将DefaultListCellRenderer中的ListCellRenderer设置为LayoutManager来实现。由于将仅添加单个组件(即JPanelGridBagLayout),因此它将居中。

遵循示例代码:

DefaultListCellRenderer

以及示例屏幕截图(具有选定的元素):

Sample screenshot with one item selected.