Question

I need to handle event from JScrollPane when user scrolls it. In here it is suggested to use addAdjustmentListener to either JViewport or Vertical/HorizontalScrollBar.

Is there any difference, which method should I choose?

I would like also to use scrollRectToVisible for the same JScrollPane, should I anticipate AdjustmentListener working for this method?

Also I wonder whether scrollRectToVisible tries to do minimum scrolling to make required rectangular visible or it tries to make it visible in the middle of JViewport ?

UPD: Requirements:

1) There a JScrollPane with one JPanel which has many JLabel(ImageIcon), so some of them are not visible.

2) When a network event comes I need to show one of JLabel (make it visible) to user. If I is not visible originally then JScrollPane should scroll automatically. That's why I mention scrollRectToVisible.

3) Above that JLabel with ImageIcon inside I need to show a message which would explain what has happened to this element. The message currently is implemented as another JLabel with floats thanks to JLayeredPane much higher in hierarchy. The problem now is that if user scrolls JScrollPane that floating JLabel should move accordingly to be on top of correponding JLabel(ImageIcon).

UDP2: SSCCE

I have not implemented floating JLabel yet, but already I don't like how label with index 11 reacts to scrollRectToVisible since it is half cropped.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class JScrollPaneTest {
    protected ArrayList<JLabel> labels = new ArrayList<JLabel>();

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new JScrollPaneTest();
            }
        });
    }

    public JScrollPaneTest() {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());

                JPanel panel1 = new JPanel ();

                panel1.setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();

                for (int i = 0; i < 20; i++) {
                    JLabel label = new JLabel("  | Label" + i + " |  ");
                    panel1.add(label, gbc);
                    labels.add(label);
                }

                panel1.addMouseListener(new MouseAdapter(){
                    public void mousePressed (MouseEvent me) {
                        JLabel label = labels.get(11);
                        label.scrollRectToVisible(label.getBounds());
                    }
                });

                JScrollPane pane = new JScrollPane(panel1) {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(600, 400);
                    }
                };

                pane.getHorizontalScrollBar().addAdjustmentListener(new AdjustmentListener() {
                    @Override
                    public void adjustmentValueChanged(AdjustmentEvent e) {
                        System.out.println("adjustmentValueChanged: " + e);
                    }
                });

                frame.getContentPane().add(pane);

                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}
Was it helpful?

Solution

Part of the answer (code in comments is just ... and noticed I had it wrong in the comment ;-)

The method scrollRectToVisible takes a Rectangle in the coordinate system of the component it is called upon. To scroll a child such that it is completely visible, there are basically two options (use one of them):

// either call on child with zero offset
child.scrollRectToVisible(new Rectangle(child.getSize());
// or call on child's parent with child bounds
child.getParent().scrollRectToVisible(child.getBounds());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top