在MouseEvent上绘制可见的JComponents

时间:2015-10-04 20:48:10

标签: java swing mousemove

我正在尝试编写一个主要用于演示的简单Java应用程序,但由于某些原因它不起作用。它的主要功能是基本跟踪鼠标的移动,并在鼠标所在的任何地方绘制一个框。我一直在研究一些代码,这就是我所拥有的。我做错了吗?

这是主要类

package peter;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.MouseInfo;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Frame extends JPanel implements MouseMotionListener {

    private final static JFrame window = new JFrame();

    public Frame(){
        addMouseMotionListener(this);
        setPreferredSize(new Dimension(450, 450));
        setBackground(Color.GREEN);   
    }

    private static int mouseX;
    private static int mouseY;
    public static void main(String[] args){
        //Create and set up the window.
        JFrame frame = new JFrame("MouseMotionEventDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        JComponent newContentPane = new Frame();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }
    @Override
    public void mouseDragged(MouseEvent e)
    {
        ;
    }
    @Override
    public void mouseMoved(MouseEvent e)
    {
        JComponent P = new Paintings();
        window.add(P);
        System.out.println("Mouse moved");
    }

    public static int getMouseY()
    {
        return MouseInfo.getPointerInfo().getLocation().y;
    }
    public static int getMouseX()
    {
        return MouseInfo.getPointerInfo().getLocation().x;
    }

    public static Rectangle rectOnMouse()
    {
        Rectangle rect = new Rectangle(getMouseX(), getMouseY(), 10,10);    
        return rect;
    }
}

这是绘画课程

package peter;

import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;

public class Paintings extends JComponent{

    public void paintComponent(Graphics g)
    {
        Graphics2D g2d = (Graphics2D) g;
        g2d.draw(Frame.rectOnMouse());
    }
}

2 个答案:

答案 0 :(得分:4)

您不想继续在MouseMotionListener中添加组件。只需更改矩形的位置并绘制它。此外,您希望将MouseListener或MouseMotionListener添加到绘图组件,否则您的鼠标点可能会关闭。例如:

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;

@SuppressWarnings("serial")
public class SimpleDraw extends JPanel {
    private static final int PREF_W = 450;
    private static final int PREF_H = PREF_W;
    private static final Dimension RECT_DIM = new Dimension(10, 10);
    private Rectangle rect = null;

    public SimpleDraw() {
        addMouseMotionListener(new MyMouse());
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        if (rect != null) {
            g2.draw(rect);
        }
    }

    // so this JPanel's is sized correctly 
    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

    private class MyMouse extends MouseAdapter {

        @Override
        public void mouseMoved(MouseEvent e) {
            // simply change the Rectangle
            rect = new Rectangle(e.getPoint(), RECT_DIM);
            repaint();  // and have the JVM re-paint this JPanel
        }
    }

    private static void createAndShowGui() {
        SimpleDraw mainPanel = new SimpleDraw();

        JFrame frame = new JFrame("SimpleDraw");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        // initialize our GUI on the Swing event thread
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGui();
            }
        });
    }
}

有关Swing绘图的更多信息:

您的代码存在其他问题:

  • 您希望避免让您的视图类(例如Frame)实现您的侦听器接口,因为它可能会变得混乱且无法很好地扩展。
  • 你过度依赖静态方法,这样做会使OOP失去优势,主要是OOP帮助降低复杂性的能力。
  • 您的mouseMoved方法再次创建新的绘图组件,并将它们连续添加到JFrame。这不仅是不必要的,因为新组件将是资源和内存占用,并且将覆盖JFrame contentPane上的任何内容,包括具有MouseMotionListener的Frame实例,这是有害的。您想要将一个作为绘图组件的组件添加到顶级窗口,并只添加一次,在我的代码中它是我的SimpleDraw类的一个实例。 mouseMoved方法应该用于移动逻辑实体,在我的代码中调用rect,然后调用repaint()

答案 1 :(得分:0)

我的猜测是你还需要在每次更新后对你正在绘制的任何组件调用repaint()方法。此外,您只需要添加一次绘画方法。你想要做的只是从鼠标监听器调用它。 在主函数中创建P并将其添加到窗口中 致电P.repaint();来自鼠标听众。 阅读关于paintComponent()和MouseListeners的oracle文档。