当前位置: 首页 > 面试题库 >

Java Swing:具有ListCellRenderer的JList所选项目的高度不同

吴康平
2023-03-14
问题内容

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

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);
    }
}

在评论中,您可以看到我已经尝试过的内容。

我已经搜索了很长时间,发现了很多无用的文章,其中一些涉及ListCellRenderer / dynamic
height,但是它们只能工作,因为单个单元格的高度保持不变。我的身高正在变化,那么我该怎么做?


问题答案:

多亏了Rastislav Komara,我得以轻松解决此问题:

我创建了一个扩展BasicListUI的内部类,并创建了在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()效果不佳。

编辑:
也检查nevster和kleopatra的分析器,它们看起来更聪明,请首先尝试…



 类似资料:
  • 问题内容: 谁能告诉我从我删除所选项目的简便方法? 我在Google和此处进行了搜索,但发现了很多方法。我应该使用哪种方式? 问题答案: 正如@Andreas_D所说,以数据为中心,更抽象的ListModel是解决方案。这可以是DefaultListModel。您应该在JList中显式设置模型。所以(感谢@kleopatra发表评论): DefaultListModel中有几种方法。 顺便说一句,

  • 因此,我今天的梁工作以以下警告结束: /usr/local/lib/python2。7/dist包/apache_-beam/runners/dataflow/dataflow_-runner。py:800:BeamDeprecationWarning:自第一个稳定版本以来,选项已被弃用。提及。选项将不受支持 所以据我所知,与其这样做: 我将不得不谈到这一点: 但有一个问题,很多选项不再可用,例如

  • 当用户点击按钮时,我试图从JList中删除选中的项目。 目前我有这样的东西: 当我单击按钮删除项目时,出现以下错误: 如何修复此错误,以及我的代码是否删除了多个项目?

  • 问题内容: 我需要的是一个返回一个面板的面板,该面板的左侧是一个图标,右侧是一个动态长度的文本(就像在任何论坛中一样:左侧是用户头像,右侧是发布文本)。该文本 不 知道我,所以我不能设置一个固定的单元格高度。此外,每个列表单元格的文本长度都不同。因此,每个列表单元格都需要自己的高度,具体取决于文本的长度。实际上是一个非常普通的布局……但对于Swing而言却不是。单元格的高度只是不会根据文本的长度而

  • 问题内容: 我有一个,我正在显示一些ID。我想捕获用户单击的ID并将其显示在上。 上面的代码为我提供了选定的值。但是此代码必须放置在button事件中,当我单击按钮时,它将获得JList值并将其分配给。 但是,我想做的是,只要用户单击其中的一项以实时更新。(无需单击按钮即可触发操作) 问题答案: 一个简单的示例如下所示,使用listselectionlistener

  • 问题内容: 我有2张表: 命令: 和Order_details: 我需要做的是选择所有具有多个Order_detail的订单,并且订单状态必须为“ OK”,并且每个order_detail的状态都 必须 为(S1,S2) 我做了这样的事情: 但这将返回所有具有多个Order_details满足条件的订单。 我确定这部分很好: 但是我必须检查以上订单的每个Order_detail是否都具有状态IN(