Peter_Browning
Peter_Browning

Reputation: 259

Drawing visible JComponents on MouseEvent

I'm trying to code a simple java application that is mainly meant for a demonstration, but it won't work for some reason. The main function of it is to basically track the mouse's movements, and draw a box wherever the mouse is. I've been working on some code already, and this is what I have. Am I doing something wrong?

This is the main class

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;
    }
}

This is the Paintings class

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());
    }
}

Upvotes: 1

Views: 48

Answers (2)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285403

You don't want to keep adding components within your MouseMotionListener. Just change the position of a Rectangle and draw it. Also, you want to add the MouseListener or MouseMotionListener to the drawing component, else your mouse point may well be off. For example:

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();
            }
        });
    }
}

For more on Swing drawing:

Other issues with your code:

  • You'll want to avoid having your view classes, Frame for instance, implement your listener interfaces as that can get messy and does not scale well.
  • You're over-relying too much on static methods, and by doing this loose the OOP advantages, mainly OOP's ability to help reduce complexity.
  • Again your mouseMoved method creates new Paintings components and adds them continuously to the JFrame. This is not only unnecessary, it's deleterious as the new components will be resource and memory hogs, and will cover up anything on the JFrame contentPane before, including a Frame instance that has your MouseMotionListener. You want to add one component that is the drawing component to the top-level window, and add it only once, here in my code it's an instance of my SimpleDraw class. The mouseMoved method should be for moving a logical entity, in my code called rect, and then for calling repaint().

Upvotes: 4

Alexandru Babeanu
Alexandru Babeanu

Reputation: 59

My guess is that you also need to call the repaint() method on whatever component you're drawing on, after every update. Also, you only need to add the painting method once. What you want to do is just call it from the mouse listener. Create P and add it to the window while in the main function.
Call P.repaint(); from the mouse listener. Read the oracle documentation on paintComponent() and MouseListeners.

Upvotes: 0

Related Questions