简体   繁体   中英

How do i use the Graphics object of a class from an Outer class

I am learning the java awt and swing libs.In this program i am trying to emulate the pencil tool from MSPaint.It works fine when i do the programming in a single class,however,does not work when i use an Outer class to listen to my Mouse motions.My guess is that i am failing to get the Graphics object of application,please enlighten me on where i am going wrong.Thanks!
Here's the code

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;

public class Paint extends Canvas {

    Paint() {
        Outer obj=new Outer(this);
        JFrame frame=new JFrame("Paint");
        frame.setSize(400,400);
        frame.add(this);
        frame.addMouseMotionListener(obj);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        new Paint();
    }
}

class Outer implements MouseMotionListener {

    static int x,y,x1,y1;

    Paint ob;

    Outer(Paint ob) {
        this.ob=ob;
    }

    public void mouseDragged(MouseEvent me) {
        Graphics g=ob.getGraphics();
        x1=me.getX();
        y1=me.getY();
        _paint_(g,x,y,x1,y1);
        x=x1;
        y=y1;
    }

    public void _paint_(Graphics g,int x,int y,int x1,int y1) {
        g.drawLine(x,y,x1,y1);
    }

    public void mouseMoved(MouseEvent me) {
        y=me.getY();
        x=me.getX();
    }
}

By does not work,i mean that the frame shows up,but the "pencil tool" does not draw lines

If you want to do this with JavaFX you can read this documentation's tutorial which contains an exact example of what you are looking for. Simply download the CanvasDoodleTest.zip and run it.

If you want to do this with Java Swing you can do it, generally speaking, like so:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Path2D;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class SwingCanvas extends JPanel implements MouseListener, MouseMotionListener {
    private final Path2D pencilPath; //This will be the Shape we are going to paint in 'myPaint(...)' method.

    public SwingCanvas() {
        pencilPath = new Path2D.Double(); //Create a new path object, i.e. a set of points and lines between them.

        super.addMouseListener(this); //Register this object as its MouseListener (for the mousePressed event).
        super.addMouseMotionListener(this); //Register this object as its MouseMotionListener (for the mouseDragged event).
        super.setPreferredSize(new Dimension(400, 200)); //Set the preferred size of the component (i.e. the size we want the panel to start with).
        super.setBackground(Color.WHITE); //[Optional] Setting the background color of the panel to white.
        super.setOpaque(true); //Opaque components are responsible to paint their full contents. This is the default behaviour of JPanel, so this is an optional call here.
    }

    /**
     * Overriding paintComponent(...) tells Swing how to paint the panel.
     * @param graphics 
     */
    @Override
    public void paintComponent(final Graphics graphics) {
        super.paintComponent(graphics); //Call this in order to clear previous painting state and start over.
        final Graphics2D g2d = (Graphics2D) graphics.create(); //Create a Graphics2D object to paint.
        try {
            myPaint(g2d); //Call our custom paint method.
        }
        catch (final RuntimeException re) { //Catch any exception in our myPaint (eg a NullPointerException) (if any).
            System.err.println(re); //Handle the exception in some way.
        }
        finally {
            g2d.dispose(); //ALWAYS dispose the CREATED Graphics2D object.
        }
    }

    /**
     * Do whatever painting you need here.
     * In our case, we draw the full path the pencil has followed.
     * @param g2d The {@link Graphics2D} object to paint on.
     */
    protected void myPaint(final Graphics2D g2d) {
        g2d.draw(pencilPath);
    }

    @Override
    public void mousePressed(final MouseEvent e) {
        pencilPath.moveTo(e.getX(), e.getY()); //Move the drawing pencil (without drawing anything new) to the new position.
    }

    @Override
    public void mouseClicked(final MouseEvent e) {
        //Do nothing.
    }

    @Override
    public void mouseReleased(final MouseEvent e) {
        //Do nothing.
    }

    @Override
    public void mouseEntered(final MouseEvent e) {
        //Do nothing.
    }

    @Override
    public void mouseExited(final MouseEvent e) {
        //Do nothing.
    }

    @Override
    public void mouseMoved(final MouseEvent e) {
        //Do nothing.
    }

    @Override
    public void mouseDragged(final MouseEvent e) {
        if (pencilPath.getCurrentPoint() == null) //If the initial point of the path is not set (via a call to "moveTo(...)") then:
            pencilPath.moveTo(e.getX(), e.getY()); //Register the new point from which the new lines will be drawn.
        else
            pencilPath.lineTo(e.getX(), e.getY()); //Register a new line in the path to be drawn.
        repaint(); //Notify Swing to repaint the component (which will call paintComponent(...) which will call myPaint(...) which will paint the pencilPath...
    }

    public static void main(final String[] args)  {
        final JFrame frame = new JFrame("SwingPaint pencil"); //Creates a new application's window.
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Tells the new window to close the application if the user closes the window.
        frame.getContentPane().add(new SwingCanvas()); //Add our custom painting panel to the window's content pane.
        frame.pack(); //Automatic sizing of the window, based on preferred sizes of contained components.
        frame.setLocationRelativeTo(null); //Put the window in the center of the screen.
        frame.setVisible(true); //Pop the window.
    }
}

If you want, you can also combine the two methods, because Canvas is a Component (so it can be added to the main frame's content pane in the Swing example).

If you want to access MouseEvent s of SwingCanvas from another class, then you can extend a MouseAdapter and add it to the panel.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM