【问题标题】:How to make JScrollPane scroll 1 line per mouse wheel step?如何让 JScrollPane 每个鼠标滚轮步骤滚动 1 行?
【发布时间】:2012-07-09 00:01:11
【问题描述】:

我有一个 JScrollPane,它的内容窗格是一个 JXList。当我在列表上使用鼠标滚轮时,列表一次会执行三 (3) 个项目。这也适用于表格,无论行高如何。我该如何更改它,以便 - 无论平台如何 - 对于列表和表格,滚动距离都是 1 项?设置块增量不会削减它,因为表中的某些行具有不同的高度。

【问题讨论】:

  • @trashgod 有一阵子没看 - 轮子似乎真的以某种方式映射到 unitIncrement,并且确实处理了各个行高,所以我的怀疑是错误的。毕竟,调整可滚动实现可能会有所帮助:-)
  • 见camickr的Mouse Wheel Controller
  • @aterai hach​​ .. 忘了那个 :-) 绝对是要走的路,考虑让您的评论成为答案,以获得一些真正的选票。
  • @kleopatra,感谢您的补充说明。我把这个留给你。

标签: java swing jscrollpane swingx


【解决方案1】:

出于纯粹的兴趣(还有一点无聊),我创建了一个工作示例:

/**
 * Scrolls exactly one Item a time. Works for JTable and JList.
 *
 * @author Lukas Knuth
 * @version 1.0
 */
public class Main {

    private JTable table;
    private JList list;
    private JFrame frame;

    private final String[] data;

    /**
     * This is where the magic with the "just one item per scroll" happens!
     */
    private final AdjustmentListener singleItemScroll = new AdjustmentListener() {
        @Override
        public void adjustmentValueChanged(AdjustmentEvent e) {
            // The user scrolled the List (using the bar, mouse wheel or something else):
            if (e.getAdjustmentType() == AdjustmentEvent.TRACK){
                // Jump to the next "block" (which is a row".
                e.getAdjustable().setBlockIncrement(1);
            }
        }
    };

    public Main(){
        // Place some random data:
        Random rnd = new Random();
        data = new String[120];
        for (int i = 0; i < data.length; i++)
            data[i] = "Set "+i+" for: "+rnd.nextInt();
        for (int i = 0; i < data.length; i+=10)
            data[i] = "<html>"+data[i]+"<br>Spacer!</html>";
        // Create the GUI:
        setupGui();
        // Show:
        frame.pack();
        frame.setVisible(true);
    }

    private void setupGui(){
        frame = new JFrame("Single Scroll in Swing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
        frame.add(split);

        // Add Data to the table:
        table = new JTable(new AbstractTableModel() {
            @Override
            public int getRowCount() {
                return data.length;
            }

            @Override
            public int getColumnCount() {
                return 1;
            }

            @Override
            public Object getValueAt(int rowIndex, int columnIndex) {
                return data[rowIndex];
            }
        });
        for (int i = 0; i < data.length; i+=10)
            table.setRowHeight(i, 30);
        JScrollPane scroll = new JScrollPane(table);
        // Add out custom AdjustmentListener to jump only one row per scroll:
        scroll.getVerticalScrollBar().addAdjustmentListener(singleItemScroll);
        split.add(scroll);

        list = new JList<String>(data);
        scroll = new JScrollPane(list);
        // Add out custom AdjustmentListener to jump only one row per scroll:
        scroll.getVerticalScrollBar().addAdjustmentListener(singleItemScroll);
        split.add(scroll);
    }

    public static void main(String[] agrs){
        new Main();
    }
}

真正的魔力是在自定义AdjustmentListener 中完成的,我们每次将当前的“滚动位置”增加一个块。如示例所示,这适用于上下以及不同的行大小。


正如 @kleopatra 在 cmets 中提到的,您也可以使用 MouseWheelListener 仅重新定义鼠标滚轮的行为。

见官方教程here

【讨论】:

  • 这真是太棒了。太感谢了!我的意思是,当然,在某处/可能/有一个 .setScrollIncrement(int i),但这样它也可以工作。顺便说一句:此代码使滚动条的页面功能(单击句柄外的条)滚动小步骤,考虑到您的代码将块增量“全局”设置为 1,这并不奇怪。有什么办法可以改变鼠标滚轮的步长吗?另外,你能推荐一本关于 Swing 的书吗?
  • 啊,要多评论一下。我很好奇为什么每次调用 AdjustmentListener 时都必须调用 setBlockIncrement(1),所以我停用了侦听器并在创建滚动窗格时调用了一次 setBlockIncrement(1)。看哪!这也有同样的副作用。我不记得这对我的办公室机器有什么影响,所以我明天在工作中测试它。有时我不喜欢 Swing。 ;-)
  • @xmjx for swing,请阅读 sun/oracle 提供的教程。我没有为此读过专门的书。 Swing 非常强大,但它也不是最小的 GUI 框架。
  • -1 用于在有高级方法时进入低级;-) scrollPane 的 wheelListener 是决定滚动量的位置:默认通过滚动每个单位的数量来实现由操作系统控制面板设置的缺口。如果需要,这就是要更改的位置:只需将一个缺口映射到自定义 MouseWheelListener 中的一个单元。
  • @kleopatra 我不知道那个听众。我相应地更新了我的答案,感谢您指出。
【解决方案2】:

代码太多,简单解释一下:

JLabel lblNewLabel = new JLabel("a lot of line of text...");
JScrollPane jsp = new JScrollPane(lblNewLabel);
jsp.getVerticalScrollBar().setUnitIncrement(10); //the bigger the number, more scrolling
frame.getContentPane().add(jsp, BorderLayout.CENTER);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-31
    相关资源
    最近更新 更多