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

带有多行文字和动态高度的JList

臧兴学
2023-03-14
问题内容

我需要的是一个ListCellRenderer返回一个面板的面板,该面板的左侧是一个图标,右侧是一个动态长度的文本(就像在任何论坛中一样:左侧是用户头像,右侧是发布文本)。该文本

知道我,所以我不能设置一个固定的单元格高度。此外,每个列表单元格的文本长度都不同。因此,每个列表单元格都需要自己的高度,具体取决于文本的长度。实际上是一个非常普通的布局……但对于Swing而言却不是。单元格的高度只是不会根据文本的长度而扩展。

我已经在中阅读了几乎所有有关动态单元格高度和多行文本的文章JList,但是找不到解决方案。所以我决定给一个小的SSCCE。请给我有关如何实现我所描述的内容的提示,或者,如果您认为很简单,请修复我的代码。

谢谢

这是SSCCE:

public class MultiLineList extends JFrame
{

    private static final long serialVersionUID = 1L;

    public static void main(final String[] args)
    {
        new MultiLineList();
    }

    private MultiLineList()
    {
        setTitle("MultiLineList");
        setSize(800, 450);
        setResizable(true);
        setVisible(true);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        this.getContentPane().setLayout(new BorderLayout());

        final DefaultListModel model = new DefaultListModel();
        model.addElement("This is a short text");
        model.addElement("This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. ");
        model.addElement("This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. ");

        final JList list = new JList(model);
        list.setCellRenderer(new MyCellRenderer());

        this.add(list);

        this.getContentPane().invalidate();
        this.getContentPane().validate();

    }

    public class MyCellRenderer extends DefaultListCellRenderer
    {
        @Override
        public Component getListCellRendererComponent(final JList list, final Object value, final int index, final boolean isSelected, final boolean hasFocus)
        {

            final String text = (String) value;

            //create panel
            final JPanel p = new JPanel();
            p.setLayout(new BorderLayout());

            //icon
            final JPanel IconPanel = new JPanel(new BorderLayout());
            final JLabel l = new JLabel("icon"); //<-- this will be an icon instead of a text
            IconPanel.add(l, BorderLayout.NORTH);
            p.add(IconPanel, BorderLayout.WEST);

            //text
            final JTextArea ta = new JTextArea();
            ta.setText(text);
            ta.setLineWrap(true);
            ta.setWrapStyleWord(true);
            p.add(ta, BorderLayout.CENTER);

            return p;

        }
    }

}

问题答案:

编辑1 :哎呀-看到@Andrew的屏幕截图,意识到这不能按预期工作,文本实际上比显示的要长(忽略了内部注释“
PENDING:不适用于JScrollPane中的JList” ;-)将挖出一个如果我无法尽快解决,请删除该答案。

编辑2 :知道了-如下所示的渲染器实现是可以的,罪魁祸首是JList,它偶尔会出现小于最佳大小的缓存。其中有两个部分

  • BasicListUI没有考虑到调整列表大小可能需要清除内部大小(实际上是行高)缓存,应用程序代码必须强制这样做,例如在ComponentListener中
  • list的tracksViewportWidth的Scrollable实现包含妨碍逻辑的逻辑(导致对该区域进行循环扩展,直到它成为单行为止),子类返回true。

使用以下渲染器的代码:

    final JList list = new JList(model) {

        /** 
         * @inherited <p>
         */
        @Override
        public boolean getScrollableTracksViewportWidth() {
            return true;
        }


    };
    list.setCellRenderer(new MyCellRenderer());

    ComponentListener l = new ComponentAdapter() {

        @Override
        public void componentResized(ComponentEvent e) {
            // next line possible if list is of type JXList
            // list.invalidateCellSizeCache();
            // for core: force cache invalidation by temporarily setting fixed height
            list.setFixedCellHeight(10);
            list.setFixedCellHeight(-1);
        }

    };

    list.addComponentListener(l);
    add(new JScrollPane(list));

第一个答案 (使用JTextArea作为呈现组件的呈现器实现)

TextArea在调整大小时有些棘手:需要将其初始化为合理的值:

public class MyCellRenderer implements ListCellRenderer {

    private JPanel p;
    private JPanel iconPanel;
    private JLabel l;
    private JTextArea ta;

    public MyCellRenderer() {
        p = new JPanel();
        p.setLayout(new BorderLayout());

        // icon
        iconPanel = new JPanel(new BorderLayout());
        l = new JLabel("icon"); // <-- this will be an icon instead of a
                                // text
        iconPanel.add(l, BorderLayout.NORTH);
        p.add(iconPanel, BorderLayout.WEST);

        // text
        ta = new JTextArea();
        ta.setLineWrap(true);
        ta.setWrapStyleWord(true);
        p.add(ta, BorderLayout.CENTER);
    }

    @Override
    public Component getListCellRendererComponent(final JList list,
            final Object value, final int index, final boolean isSelected,
            final boolean hasFocus) {

        ta.setText((String) value);
        int width = list.getWidth();
        // this is just to lure the ta's internal sizing mechanism into action
        if (width > 0)
            ta.setSize(width, Short.MAX_VALUE);
        return p;

    }
}


 类似资料:
  • 问题内容: 我有这个HTML结构: 我想在主体部分(#body)中包含三个部分而不会溢出。因此,我需要在中间部分使用滚动条。 我尝试了这个CSS: 和这个: 但是它们都不起作用。 我在JSFiddle上做了一个例子。 我可以仅使用CSS和HTML来做到这一点吗?我宁愿避免使用Javascript。 问题答案: Flexbox是一种现代替代方案,可让您无需固定高度或JavaScript即可执行此操作

  • 我目前正在使用一个将生成报告的API(使用JasperReports 6.12.2),在这种情况下,我必须在文本字段中打印一个大字符串,问题是我不能给这个元素赋予appiate行为来调整字符串大小的高度。 我以前一直在搜索询问,我找到的只是关于的属性,但对我不起作用,因为在我的版本中,这是不推荐的,而是用替换,所以基本上所有的结果都是一样的,文本被文本字段剪切。 注意:另外,我不得不说,这种动态的

  • 问题内容: 我有一个表格视图,其中包含一个webView的单元格,我希望该单元格的高度与该webView的高度相匹配。 这是我使用的代码: 结果是这样的:https : //postimg.cc/image/8qew1lqjj/ 该webView是正确的高度,但单元格不是,如何解决此问题? 问题答案: TableView会自动调整单元格的大小,您只需要实现委托方法即可。 是的,您最初并不知道Web

  • 本文向大家介绍ios动态设置lbl文字标签的高度,包括了ios动态设置lbl文字标签的高度的使用技巧和注意事项,需要的朋友参考一下 方法二: 方法三:

  • 关于文本字段的设置,我有以下内容 isStretchWithOverflow=“true” positiontype=“float” StretchType=“RelativeTotallestObject” 细节带有以下设置: null 谢谢。

  • 我试图实现带有水平滚动的,所以我使用了带有水平方向的。问题是,我使用2种不同类型的项目填充RecyclerView,具有不同的高度。这是我对项目使用的布局: 这是包含的布局,基本上是这样的: 我使用的是一个,我只是更改了两个子视图的可见性。 我希望得到的结果是: 但我得到的是这个;使用第二种物品的高度将CardView切成两半: 我看到了这个帖子,和我的问题差不多,它推荐使用,于是,我尝试实现: