如何使 JLabel 在 JScrollPane 中浮动在同一个 JComponent 之上



JScrollPane里面有20个JLabel s。还有浮点标签与上面提到的JscrollPane一起添加到JLayeredPane

要求是当我在JScrollPane内部单击时,它应该自动滚动以使索引为 11 的JLabel完全可见。此外,当用户滚动JScrollPane时,floatingLabel 应该开始浮动在 11 JLabel上方,请参阅AdjustmentListener

问题 [编辑]:1. 如何检查 JLabel 11 是否完全或部分不可见?

SSCCE:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Point;
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.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class JScrollPaneTest {
    protected ArrayList<JLabel> labels = new ArrayList<JLabel>();
    protected JLabel floatingLabel = new JLabel("floating");
    protected JFrame frame;
    protected JScrollPane sPane;
    protected JLayeredPane lPane;
    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() {
                frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                lPane = new JLayeredPane() {
                    private static final long serialVersionUID = 1L;
                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(800, 600);
                    }
                };
                JPanel panel = new JPanel ();
                panel.setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                for (int i = 0; i < 20; i++) {
                    JLabel label = new JLabel("  | Label" + i + " |  ");
                    panel.add(label, gbc);
                    labels.add(label);
                }
                panel.addMouseListener(new MouseAdapter(){
                    public void mousePressed (MouseEvent me) {
                        JLabel label = labels.get(11);
                        label.scrollRectToVisible(label.getBounds());
                        Point loc = label.getLocation();
                        Point wrPos = SwingUtilities.convertPoint(label, loc, lPane);
                        floatingLabel.setLocation(wrPos);
                        floatingLabel.setVisible(true);
                    }
                });
                sPane = new JScrollPane(panel) {
                    private static final long serialVersionUID = 1L;
                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(600, 400);
                    }
                };
                sPane.getHorizontalScrollBar().addAdjustmentListener(new AdjustmentListener() {
                    @Override
                    public void adjustmentValueChanged(AdjustmentEvent ae) {
                        System.out.println("adjustmentValueChanged: " + ae.getValue());
                        //if label11 is not visible
                        //floatingLabel.setVisible(false);
                        //else floatingLabel.setLocation();
                    }
                });
                lPane.add(sPane, JLayeredPane.PALETTE_LAYER);
                sPane.setBounds(100, 100, (int)sPane.getPreferredSize().getWidth(), (int)sPane.getPreferredSize().getHeight());
                lPane.add(floatingLabel, JLayeredPane.POPUP_LAYER);
                floatingLabel.setBounds(100, 100, 50, 30);
                floatingLabel.setBorder(BorderFactory.createLineBorder(Color.red));
                frame.getContentPane().add(lPane);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}

已解决的问题:

  1. JLabel 11 点击后不完全可见,它是半裁剪的
  2. 我无法计算浮动的正确位置单击面板
  3. 我不知道如何在滚动时计算新位置
label.scrollRectToVisible(new Rectangle(0,0,label.getWidth(), label.getHeight()));

在单击中改用它

public void mousePressed (MouseEvent me) {
  JLabel label = labels.get(11);
  label.scrollRectToVisible(new Rectangle(0,0,label.getWidth(), label.getHeight()));
  //Point loc = label.getLocation();
  Point loc = new Point(0,0);
  Point wrPos = SwingUtilities.convertPoint(label, loc, lPane);
  floatingLabel.setLocation(wrPos);
  floatingLabel.setVisible(true);
}
public void adjustmentValueChanged(AdjustmentEvent ae) {
  System.out.println("adjustmentValueChanged: " + ae.getValue());
  JLabel label = labels.get(11);
  Point loc = new Point(0,0);
  Point wrPos = SwingUtilities.convertPoint(label, loc, lPane);
  floatingLabel.setLocation(wrPos);
  floatingLabel.setVisible(true);
}

最新更新