Java Swing:JList与ListCellRenderer选择的项目高度不同 [英] Java Swing: JList with ListCellRenderer selected item different height

查看:617
本文介绍了Java Swing:JList与ListCellRenderer选择的项目高度不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作自定义ListCellRenderer。我知道每个单元格可以有不同的尺寸。但是现在我希望为所选单元格设置不同的维度。不知何故,JList在第一次计算每个单元格的边界时,为每个单独的单元格缓存维度。
这是我的代码:

I'm making a custom ListCellRenderer. I know that you can have different dimensions for each individual cell. But now I want to have a different dimension for the selected cell. Somehow, the JList is caching the dimension for each individual cell the first time it has to calculate bounds for each cell. This is my code:

public class Test {

    static class Oh extends JPanel {

        public Oh() {
            setPreferredSize(new Dimension(100, 20));
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.WHITE);
            g.fillRect(0, 0, getWidth(), getHeight());
        }
    }

    static class Yeah extends JPanel {
        private boolean isSelected;

        public Yeah(boolean isSelected) {
            setPreferredSize(new Dimension(100, 100));
            this.isSelected = isSelected;
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            //setSize(100, 100); // doesn't change the bounds of the component
            //setBounds(0, 0, 100, 100); // this doesn't do any good either.
            if (isSelected) g.setColor(Color.GREEN);
            else g.setColor(Color.BLACK);
            g.fillRect(0, 0, getWidth(), getHeight());
        }
    }

    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.setSize(800, 500);
        Vector<Integer> ints = new Vector<Integer>();
        for (int i = 0; i < 100; i++) {
            ints.add(i);
        }
        JList list = new JList(ints);
        list.setCellRenderer(new ListCellRenderer() {
            public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                if (isSelected || ((Integer) value) == 42) return new Yeah(isSelected);
                else return new Oh();
            }
        });
        //list.setPrototypeCellValue(null);
        //list.setFixedCellHeight(-1);
        f.add(new JScrollPane(list));
        f.setVisible(true);
    }
}

在评论中你可以看到我已经知道的东西试过了。

In the comments you can see what I've already tried.

我已经搜索了很长时间,发现了很多无用的文章,其中一些触及ListCellRenderer /动态高度的东西,但它们只能起作用,因为它的高度对于单个细胞保持不变。我的高度正在改变,所以我该怎么做?

I've already searched quite long and found a lot of useless articles, some of them touch the ListCellRenderer/dynamic height thing, but they only work because the height stays the same for the individual cells. My heights are changing, so how do I do this?

推荐答案

感谢Rastislav Komara我已经能够解决这个问题了容易:

Thanks to Rastislav Komara I've been able to solve this quite easily:

我创建了一个扩展BasicListUI的内部类,并创建了在ListSelectionListener.valueChanged上调用的公共方法:

I've created an inner class that extends BasicListUI and created public method that is called on ListSelectionListener.valueChanged:

private class MyRenderer implements ListCellRenderer {
    public int listSelectedIndex = -1;

    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
            boolean cellHasFocus) {
        if (index == listSelectedIndex)
            return new Yeah(isSelected);
        else
            return new Oh();
    }
}
MyRenderer lcr = new MyRenderer();
private class MyListUI extends BasicListUI {

    public void triggerUpdate() {
        lcr.listSelectedIndex = list.getSelectedIndex();
        updateLayoutState();
        list.revalidate();
    }
}

当JList高度发生变化时,通常会触发updateLayoutState方法。
我在这里做的唯一疯狂事情是我的渲染器需要知道所选索引是什么。这是因为updateLayoutState方法在其高度计算中不使用所选索引。
以某种方式在getListCellRendererComponent中使用list.getSelectedIndex()不能正常工作。

The updateLayoutState method is normally triggered when the JList height changes. The only "insane" thing I'm doing here is that my renderer needs to know what the selected index is. This is because the updateLayoutState method doesn't use the selected index in it's height calculations. Somehow using list.getSelectedIndex() inside getListCellRendererComponent doesn't work well.

编辑:

检查nevster和kleopatra的anser,他们看起来更聪明,先试试......


Check also the anser by nevster and kleopatra, they look way smarter, try them first...

这篇关于Java Swing:JList与ListCellRenderer选择的项目高度不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆