【问题标题】:mouse coordinates offset on JPanel inside JScrollPaneJScrollPane 内 JPanel 上的鼠标坐标偏移
【发布时间】:2011-07-05 13:55:46
【问题描述】:

我在 JScrollPane 中有一个 JPanel。 JPanel 附加了一个 MouseListener 以响应鼠标事件。当我将 JPanel 直接添加到父 JComponent(中间没有 JScrollPane)时,它都可以正常工作。一旦我将 JScrollPane 添加到组合中,发送到 JPanel 上的事件处理程序的鼠标坐标在 x 和 y 轴上都有一个正偏移。

示例(JPanel 上的鼠标监听器):

public void mousePressed(MouseEvent ev) {
    System.out.println(ev.getPoint());
    System.out.println(this.getMousePosition());
}

当我单击 JPanel 的左上角而不是 (0,0) 时,我会从两个函数中得到类似 (5,60) 的结果,而右下角(对于大小为 600x400 的 JPanel)返回 (605,460)。知道这个线性偏移是从哪里来的吗?

编辑: 没关系,我将它简化为一个简单的测试用例,它按预期工作。所以它一定是我周围代码中的某些东西导致了这种行为。

public class JScrollPaneTest {
public static void main(String[] args) {
    JFrame window = new JFrame();
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);      
    window.getContentPane().setLayout(new BorderLayout());
    MyPanel panel = new MyPanel();
    window.getContentPane().add(new JScrollPane(panel), BorderLayout.CENTER);

    window.setSize(new Dimension(600, 400));
    window.setVisible(true);

}

}

public class MyPanel extends JPanel implements MouseListener, Scrollable {
public MyPanel() {
    setLayout(null);
    addMouseListener(this);
    this.setAutoscrolls(true);
}

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

@Override
public void mousePressed(MouseEvent ev) {
    System.out.println("Event mouse position: " + ev.getPoint());
    System.out.println("Panel mouse position: " + this.getMousePosition());
}
}

【问题讨论】:

  • “JPanel 附加了一个 MouseListener..” 我最好的选择是 MouseListener 附加到其他东西上。发布SSCCE,就像 mMorbel 发布的那样,以证明并非如此。
  • 是的,如果没有扩展代码示例(包括您如何创建 JPanel/JScrollPane)很难/不可能诊断此问题 - 理想情况下,发布两个示例来描述您描述的两种情况。
  • JPanel的默认布局是FlowLayout;请参阅@mKorbel 的答案。

标签: java swing event-handling jpanel jscrollpane


【解决方案1】:

请问您能否根据此示例重现您的问题?

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
import javax.swing.border.LineBorder;

public class MainViewPort {

    public static void main(String[] args) {
        JPanel viewportPanelTop = new JPanel();
        JPanel viewportPanelBottom = new JPanel();
        JPanel viewportPanel = new JPanel();
        viewportPanel.setBackground(Color.BLACK);
        viewportPanel.setPreferredSize(new Dimension(1000, 1000));
        JPanel viewportPanel1 = new JPanel();
        viewportPanel1.setBackground(Color.red);
        JPanel viewportPanel2 = new JPanel();
        viewportPanel2.setBackground(Color.blue);
        JPanel viewportPanel3 = new JPanel();
        viewportPanel3.setBackground(Color.cyan);
        JPanel viewportPanel4 = new JPanel();
        viewportPanel4.setBackground(Color.yellow);
        JPanel viewportPanel5 = new JPanel();
        viewportPanel5.setBackground(Color.LIGHT_GRAY);
        JPanel viewportPanel6 = new JPanel();
        viewportPanel6.setBackground(Color.magenta);
        viewportPanel.setLayout(new GridLayout(3, 2));
        viewportPanel.add(viewportPanel1);
        viewportPanel.add(viewportPanel2);
        viewportPanel.add(viewportPanel3);
        viewportPanel.add(viewportPanel4);
        viewportPanel.add(viewportPanel5);
        viewportPanel.add(viewportPanel6);

        viewportPanel.addMouseListener(new MouseListener() {

            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println(e.getPoint());
            }

            @Override
            public void mousePressed(MouseEvent e) {
            }

            @Override
            public void mouseReleased(MouseEvent e) {
            }

            @Override
            public void mouseEntered(MouseEvent e) {
            }

            @Override
            public void mouseExited(MouseEvent e) {
            }
        });

        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setPreferredSize(new Dimension(800, 600));
        scrollPane.setBackground(Color.BLUE);
        scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
        scrollPane.getViewport().add(viewportPanel);
        scrollPane.getViewport().setViewPosition(new Point(0, 0));
        scrollPane.getViewport().setBackground(Color.red);
        scrollPane.setBorder(new LineBorder(Color.black, 2));

        JFrame frame = new JFrame();
        frame.setTitle("Viewport JFrame");
        frame.setLocation(150, 150);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        frame.add(viewportPanelTop, BorderLayout.NORTH);
        frame.add(scrollPane, BorderLayout.CENTER);
        frame.add(viewportPanelBottom, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);
    }

    private MainViewPort() {
    }
}

【讨论】:

  • +1 好sscce。您的明确布局是关键; FlowLayout 是 OP 的原因。 MouseAdapter 会合适吗?
  • @trashgod goooood :-) 是的,我本来想把 MouseMotionListener 放在那里,但我没完没了的懒惰 :-) 和 OP 在很大程度上消散了,所以我们的任何思考都是......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-18
  • 1970-01-01
  • 1970-01-01
  • 2014-01-11
  • 2018-06-23
  • 1970-01-01
  • 2011-12-20
相关资源
最近更新 更多