JScrollPane adjustListener和scrollRectToVisible

时间:2012-11-28 12:02:07

标签: java swing jscrollpane jscrollbar jviewport

我需要在用户滚动时处理来自JScrollPane的事件。在here中,建议将addAdjustmentListener用于JViewport或Vertical / Horizo​​ntalScrollBar。

有什么区别,我应该选择哪种方法?

我还希望scrollRectToVisible使用同一个JScrollPane,我应该期望AdjustmentListener为此方法工作吗?

另外我想知道scrollRectToVisible是否尝试进行最小滚动以使所需的矩形可见,或者它是否尝试在JViewport的中间显示它?

UPD:要求:

1)有一个带有一个JPanel的JScrollPane,它有许多JLabel(ImageIcon),因此其中一些不可见。

2)当网络事件发生时,我需要向用户显示一个JLabel(使其可见)。如果我原来不可见,那么JScrollPane应该自动滚动。这就是为什么我提到scrollRectToVisible

3)在带有ImageIcon的JLabel上方,我需要显示一条消息,说明该元素发生了什么。由于JLayeredPane的层次结构要高得多,因此该消息当前作为另一个具有浮点数的JLabel实现。现在的问题是,如果用户滚动JScrollPane,浮动JLabel应该相应地移动到相应的JLabel(ImageIcon)之上。

UDP2:SSCCE

我还没有实现浮动JLabel,但我已经不喜欢索引11的标签如何对scrollRectToVisible作出反应,因为它被裁剪了一半。

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);
            }
        });
    }
}

1 个答案:

答案 0 :(得分:4)

部分答案(评论中的代码只是...并注意到我在评论中写错了; - )

方法scrollRectToVisible在调用它的组件的坐标系中获取一个Rectangle。要滚动一个孩子以使其完全可见,基本上有两个选项(使用一个):

// 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());