如何将自定义的 MouseMotionListener 添加到 JPanel?

Posted

技术标签:

【中文标题】如何将自定义的 MouseMotionListener 添加到 JPanel?【英文标题】:How to add a self-defined MouseMotionListener to a JPanel? 【发布时间】:2022-01-02 13:37:20 【问题描述】:

我为JPanel 写了一个MouseMotionListener,但我对如何使用它感到困惑。

使用aWindow.add(new MouseMotionEvents()) 将监听器类添加到框架时效果很好,但是当我尝试使用content.add(new MouseMotionEvents()) 将它添加到面板时,它不起作用。我是 Swing 和 JComponents 的新手,有人能给我一些提示吗?

public class test 

  public static void main(String[] args) 
    JFrame aWindow = new JFrame();
    aWindow.setBounds(600, 600, 600, 600);
    aWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JPanel content = new JPanel();
    content.add(new MouseMotionEvents());
    aWindow.add(content);
    
    aWindow.setVisible(true);
  


class MouseMotionEvents extends JPanel implements MouseListener,
    MouseMotionListener 
  Point p;
  Point r;

  public MouseMotionEvents() 
    addMouseListener(this);
    addMouseMotionListener(this);
  

  public void mouseClicked(MouseEvent me) 
    // p = me.getPoint();
    // repaint();
  

  public void mouseEntered(MouseEvent me) 
  

  public void mouseExited(MouseEvent me) 
  

  public void mousePressed(MouseEvent me) 
    p = me.getPoint();
    // repaint();
  

  public void mouseReleased(MouseEvent me) 
    r = me.getPoint();
    repaint();
  

  public void mouseDragged(MouseEvent me) 
    r = me.getPoint();
    repaint();
  

  public void mouseMoved(MouseEvent me) 
  

  public void paint(Graphics g) 
    if (p != null && r != null) 
      Dimension d = getSize();
      int xc = d.width / 2;
      int yc = d.height / 2;
      if(p.getX()-r.getX()>0 && p.getY()-r.getY()>0)
        g.drawRect((int)p.getX(), (int)p.getY(), (int)(p.getX()-r.getX()), (int)(p.getY()-r.getY()));
      
      if(p.getX()-r.getX()>0 && p.getY()-r.getY()<0)
        g.drawRect((int)p.getX(), (int)p.getY(), (int)(p.getX()-r.getX()), (int)(-p.getY()+r.getY()));
      
      if(p.getX()-r.getX()<0 && p.getY()-r.getY()>0)
        g.drawRect((int)p.getX(), (int)p.getY(), (int)(-p.getX()+r.getX()), (int)(p.getY()-r.getY()));
      
      if(p.getX()-r.getX()<0 && p.getY()-r.getY()<0)
        g.drawRect((int)p.getX(), (int)p.getY(), (int)(-p.getX()+r.getX()), (int)(-p.getY()+r.getY()));
      
      
    
  

【问题讨论】:

覆盖paintComponent而不是paint。 如果还是不行,在repaint()之前调用invalidate()。 还是不行, “它仍然不起作用”不要告诉我们什么不起作用。什么不工作? 我只是浏览了其他人的帖子,他们使用类似“jpanel.addMouseMotionListener(new MouseMotionAdapter() ... )”的东西,但我写的类只是实现了 MouseListener 和 MouseMotionListener,做你认为这是个问题吗? 【参考方案1】:

在您问题的代码中,您将JPanel 添加到JPanel,因为MouseMotionEventsJPanel(因为它扩展了类JPanel)。 JPanel 的默认 layout manager 是 FlowLayout,它尝试以首选大小显示其包含的组件。因此,当您运行 GUI 时,您无法真正看到 MouseMotionEvents 出现的位置。您可以通过添加以下内容为其添加边框(在类MouseMotionEvents的构造函数中)

setBorder(javax.swing.BorderFactory.createLineBorder(java.awt.Color.red));

现在当你运行 GUI 时,它看起来像这样

这是因为 JPanel 的大小为零(首选),因为它的大小由它包含的组件决定,但在您的代码中 MouseMotionEvents 不包含任何组件。您可以通过显式设置首选大小来解决此问题。这是设置合适的首选尺寸后的样子。

现在您可以在红色边框内拖动鼠标并绘制矩形。

另外,您应该重写方法 paintComponent 而不是方法 paint。参考Performing Custom Painting。

这是代码。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MouseMotionEvents extends JPanel implements MouseListener, MouseMotionListener 
    Point p;
    Point r;

    public MouseMotionEvents() 
        addMouseListener(this);
        addMouseMotionListener(this);
        setBorder(BorderFactory.createLineBorder(Color.red));
        setPreferredSize(new Dimension(300, 300));
    

    public void mouseClicked(MouseEvent me) 
        // p = me.getPoint();
        // repaint();
    

    public void mouseEntered(MouseEvent me) 
    

    public void mouseExited(MouseEvent me) 
    

    public void mousePressed(MouseEvent me) 
        System.out.println("mousePressed");
        p = me.getPoint();
        // repaint();
    

    public void mouseReleased(MouseEvent me) 
        System.out.println("mouseReleased");
        r = me.getPoint();
        repaint();
    

    public void mouseDragged(MouseEvent me) 
        r = me.getPoint();
        repaint();
    

    public void mouseMoved(MouseEvent me) 
    

    protected void paintComponent(Graphics g) 
        super.paintComponent(g);
        if (p != null && r != null) 
            Dimension d = getSize();
            int xc = d.width / 2;
            int yc = d.height / 2;
            if (p.x - r.x > 0 && p.y - r.y > 0) 
                g.drawRect(p.x, p.y, (p.x - r.x), (p.y - r.y));
            
            if (p.x - r.x > 0 && p.y - r.y < 0) 
                g.drawRect(p.x, p.y, (p.x - r.x), (-p.y + r.y));
            
            if (p.x - r.x < 0 && p.y - r.y > 0) 
                g.drawRect(p.x, p.y, (-p.x + r.x), (p.y - r.y));
            
            if (p.x - r.x < 0 && p.y - r.y < 0) 
                g.drawRect(p.x, p.y, (-p.x + r.x), (-p.y + r.y));
            
        
    

    public static void main(String[] args) 
        JFrame aWindow = new JFrame();
        aWindow.setBounds(600, 600, 600, 600);
        aWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel content = new JPanel();
        content.add(new MouseMotionEvents());
        aWindow.add(content);
        
        aWindow.setVisible(true);
    

请注意,xy 是类 Point 的公共成员,因此不需要使用方法 getXgetY,因此不需要强制转换。

当您将MouseMotionEvents 直接添加到JFrame 时,您将MouseMotionEvents 添加到带有JPanelBorderLayout 并且您将其添加到中心。由于您提供了JFrame 和明确的大小,BorderLayout 确保MouseMotionEvents 的大小在JFrame 中占用尽可能多的空间。因此MouseMotionEvents 足够大,您可以在其中拖动鼠标。

【讨论】:

【参考方案2】:

要将 MouseMotionListener 添加到 JPanel,您必须使用

myPanel.setMouseMotionListener ( myMouseListener );

并直接在您的面板上调用它,就像您在 mouseMotionEvents 类中所做的那样。这就是它起作用的原因,当您将它直接添加到您的 JFrame 时。

修复您的代码后,我得到了这个,它应该可以正常工作。我把它分成了两个类,一个是 JFrame 的主类,一个是 JPanel(内容)的主类。

主类:

public class MouseMotionListenerTest 
    public static void main ( String[] args ) 
        JFrame aWindow = new JFrame();
        aWindow.setBounds( 600, 600, 600, 600 );
        aWindow.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

        ContentPanel content = new ContentPanel();
        aWindow.add( content );

        aWindow.setVisible( true );
    

面板类:

public class ContentPanel extends JPanel 
    private Point p;
    private Point r;

    public ContentPanel () 
        MouseMotionEvents mme = new MouseMotionEvents();
        addMouseListener( mme );
        addMouseMotionListener( mme );
    

    public void paint ( Graphics g ) 
        if ( p != null && r != null ) 
            Dimension d = getSize();
            int xc = d.width / 2;
            int yc = d.height / 2;
            if ( p.getX() - r.getX() > 0 && p.getY() - r.getY() > 0 ) 
                g.drawRect( ( int ) p.getX(), ( int ) p.getY(), ( int ) ( p.getX() - r.getX() ), ( int ) ( p.getY() - r.getY() ) );
            
            if ( p.getX() - r.getX() > 0 && p.getY() - r.getY() < 0 ) 
                g.drawRect( ( int ) p.getX(), ( int ) p.getY(), ( int ) ( p.getX() - r.getX() ), ( int ) ( -p.getY() + r.getY() ) );
            
            if ( p.getX() - r.getX() < 0 && p.getY() - r.getY() > 0 ) 
                g.drawRect( ( int ) p.getX(), ( int ) p.getY(), ( int ) ( -p.getX() + r.getX() ), ( int ) ( p.getY() - r.getY() ) );
            
            if ( p.getX() - r.getX() < 0 && p.getY() - r.getY() < 0 ) 
                g.drawRect( ( int ) p.getX(), ( int ) p.getY(), ( int ) ( -p.getX() + r.getX() ), ( int ) ( -p.getY() + r.getY() ) );
            
        
    

    private class MouseMotionEvents extends MouseAdapter 
        public void mouseClicked ( MouseEvent me ) 
            // p = me.getPoint();
            // repaint();
        

        public void mousePressed ( MouseEvent me ) 
            p = me.getPoint();
            // repaint();
        

        public void mouseReleased ( MouseEvent me ) 
            r = me.getPoint();
            repaint();
        

        public void mouseDragged ( MouseEvent me ) 
            r = me.getPoint();
            repaint();
        
    

【讨论】:

以上是关于如何将自定义的 MouseMotionListener 添加到 JPanel?的主要内容,如果未能解决你的问题,请参考以下文章

如何将自定义事件添加到 jQuery 插件模式中

如何将自定义视图动画化为自定义视图

如何将自定义标记导出回 AutoCAD

如何以编程方式将自定义图像设置为 UIBarButtonItem

如何将自定义单元格连接到 UIViewController?

如何将自定义彩色图像添加到 TabBarController 中的 tabBar?