【问题标题】:How to add a self-defined MouseMotionListener to a JPanel?如何将自定义的 MouseMotionListener 添加到 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,做你认为这是个问题吗?

标签: java swing jframe jpanel mousemotionlistener


【解决方案1】:

在您问题的代码中,您将JPanel 添加到JPanel,因为MouseMotionEventsJPanel(因为它扩展了类JPanel)。 JPanel 的默认 layout managerFlowLayout,它尝试以首选大小显示其包含的组件。因此,当您运行 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();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-16
      • 2020-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-07
      • 1970-01-01
      相关资源
      最近更新 更多