You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建仅显示3项的水平JList(带滚动条)

问题描述

我尝试在JScrollPane中创建一个包含7个项的水平JList,仅让其中3项可见,其余项可通过滚动条访问,预期效果如下:
预期效果示意图

我编写了如下代码:

JFrame frame = new JFrame("JList Example");

String[] items = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10"};
JList<String> list = new JList<>(items);
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(1);

JScrollPane scrollPane = new JScrollPane(list);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

frame.add(scrollPane);

但实际效果如下:
实际效果示意图

我找不到除设置JScrollPane的setPreferredSize之外的方法来限制可见项数量,而该方法并不合适且对我无效,请问还有其他实现方式吗?

P.S. 我的英文不好,若有表述不清之处请见谅。

解决方案

要实现仅显示指定数量的水平JList项,核心是让JList根据项的实际尺寸计算自身的首选视口大小,而非硬编码尺寸。以下是两种可行方案:

方案一:基于单元格渲染器计算尺寸

通过获取默认单元格渲染器的尺寸,计算出3个项的总宽度,再设置JList的首选尺寸:

JFrame frame = new JFrame("JList Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

String[] items = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10"};
JList<String> list = new JList<>(items);
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(1);

// 获取默认渲染器,计算单个项的首选宽度
ListCellRenderer<? super String> renderer = list.getCellRenderer();
Component comp = renderer.getListCellRendererComponent(list, items[0], 0, false, false);
int singleItemWidth = comp.getPreferredSize().width;
// 计算3个项的总宽度,包含列表内边距
int preferredWidth = singleItemWidth * 3 + list.getInsets().left + list.getInsets().right;
list.setPreferredSize(new Dimension(preferredWidth, list.getPreferredSize().height));

JScrollPane scrollPane = new JScrollPane(list);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

frame.add(scrollPane);
frame.pack();
frame.setVisible(true);

方案二:重写JList的视口尺寸方法

这是更优雅的方式,符合Swing的布局机制,避免直接调用setPreferredSize:

JFrame frame = new JFrame("JList Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

String[] items = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10"};
JList<String> list = new JList<>(items) {
    @Override
    public Dimension getPreferredScrollableViewportSize() {
        // 获取第一个项的渲染组件,计算单一项宽度
        ListCellRenderer<? super String> renderer = getCellRenderer();
        Component comp = renderer.getListCellRendererComponent(this, getModel().getElementAt(0), 0, false, false);
        int itemWidth = comp.getPreferredSize().width;
        // 计算3个项的总视口宽度,包含内边距
        int viewportWidth = itemWidth * 3 + getInsets().left + getInsets().right;
        // 高度沿用默认的单行高度
        return new Dimension(viewportWidth, super.getPreferredScrollableViewportSize().height);
    }
};
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(1);

JScrollPane scrollPane = new JScrollPane(list);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

frame.add(scrollPane);
frame.pack();
frame.setVisible(true);

方案优势

  • 基于项的实际内容尺寸计算,不会因文本长度变化导致布局错位
  • 遵循Swing的布局管理器规则,适配不同外观风格(LAF)
  • 无需硬编码数值,灵活性更强

内容的提问来源于stack exchange,提问作者Obaraten64

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 03:44:53