3
votes

I have a situation like this. I have scrollpane whose viewportView is a JPanel And that JPanel has the layout as BoxLayout. In this panel I add one class which extends JPanel and that class contains JComponents.

So while running an application, the JComponents are shown in the JScrollPane. This is how my ScrollPane is formed.

The problem here is, When the data exceeds more than around 750 rows, The scrollbar starts giving problems. When scrolling up or down by mouse wheel, scroll doesnot move smoothly, It suddenly stops in the middle and again starts, say it has a jerky movement. my Question is how can i get the smooth mouse movement in this scenario.

My scrollPane is like this

public JScrollPane getScrollPane() {
    if (scrollPane == null) {
        scrollPane = new JScrollPane();
        scrollPane.setSize(new Dimension(1000, 433));
        scrollPane.setLocation(new Point(10, 10));
        scrollPane.setColumnHeaderView(getHeaderOfRowPanel());
        scrollPane
                .setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        scrollPane.setViewportView(getScrollPanel());
        scrollPane
                .setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        scrollPane.getVerticalScrollBar().setUnitIncrement(
                unitIncrement);

    }
    return scrollPane;
}

private JPanel getScrollPanel() {
    if (scrollPanel == null) {
        scrollPanel = new JPanel();
        scrollPanel.setBorder(null);
        scrollPanel.setLayout(new BoxLayout(getScrollPanel(),
                BoxLayout.Y_AXIS));
    }
    return scrollPanel;
}


private class RowPanel extends JPanel {
//My components are here ..
//I add this Panel in scrollPanel
}
3

3 Answers

3
votes

Have look at JScrollBar.setUnitIncrement, beacuse bunch of JPanels in the JScollPane has un_natural scrolling in compare with JList, JTable or JTextArea

example

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class JScrollBarUnitIncrement {

    public static void main(String[] args) {
        final JFrame f = new JFrame("");
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(2000, 1));
        for (int i = 0; i != 2000; i++) {
            JButton btn = new JButton("Button 2");
            panel.add(btn);
        }
        final JScrollPane sPane = new JScrollPane(panel);
        final int increment = 50;
        sPane.getVerticalScrollBar().setUnitIncrement(increment);
        KeyStroke kUp = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0);
        KeyStroke kDown = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0);
        sPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(kUp, "actionWhenKeyUp");
        sPane.getActionMap().put("actionWhenKeyUp", new AbstractAction("keyUpAction") {

            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) {
                final JScrollBar bar = sPane.getVerticalScrollBar();
                int currentValue = bar.getValue();
                bar.setValue(currentValue - increment);
            }
        });
        sPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(kDown, "actionWhenKeyDown");
        sPane.getActionMap().put("actionWhenKeyDown", new AbstractAction("keyDownAction") {

            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) {
                final JScrollBar bar = sPane.getVerticalScrollBar();
                int currentValue = bar.getValue();
                bar.setValue(currentValue + increment);
            }
        });
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(sPane);
        f.pack();
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                f.setVisible(true);
            }
        });
    }

    private JScrollBarUnitIncrement() {
    }
}
2
votes

It is never good to populate such huge no. of rows in JScrollPane. Because, the visible portion is only around let's say 20 to 30 rows in viewport depending on the height of the scrollpane and the height of your RowPanel. So, why to populate such huge rows at once ? The problem with the smoothness is because there might be exception (see the console ). So, resolve this, I see two options for you. One is to use pagination and another is to allow users to enter some search criteria to filter out the unwanted records.

2
votes

As @mKorbel notes, both JTable and JList implement Scrollable for convenient scroll increments, and they both use the flyweight pattern for rendering speed. If you can't use either component directly, you can still use the patterns. The tutorial includes Scrollable examples, and there's a CellRendererPane example here.