【问题标题】:Drawing visible JComponents on MouseEvent在 MouseEvent 上绘制可见的 JComponent
【发布时间】:2015-10-04 20:48:10
【问题描述】:

我正在尝试编写一个主要用于演示的简单 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());
    }
}

【问题讨论】:

  • 你的 'getMouseX()' 正在返回 'y'。
  • 我更新了代码来纠正这个问题。感谢您的意见
  • 阅读教程,因为你做了很多不正确的假设。一方面,您重复创建和添加绘画对象是错误的。为什么要反复制作组件?
  • 使用 Swing 教程开始绘制的 Swing 教程。
  • 在这种情况下不要依赖static,它很快就会陷入一场关于谁在做什么的大规模猜谜游戏。更好地直接传达您的期望/愿望

标签: java swing mousemove


【解决方案1】:

您不想在 MouseMotionListener 中不断添加组件。只需更改 Rectangle 的位置并绘制它。此外,您希望将 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()。

【讨论】:

  • 感谢您提供所有这些信息!我真的很感激!
【解决方案2】:

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

【讨论】:

  • 我试过了,还是不行,还有其他建议吗?
  • 这个答案过度简化了你的问题,并没有解决你错误的 MouseMotionListener。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-13
  • 1970-01-01
  • 2013-03-28
  • 1970-01-01
  • 2014-07-28
  • 2023-03-22
  • 1970-01-01
相关资源
最近更新 更多