简体   繁体   中英

How to draw on top of an image in Java?

I used JFrame to import and display an image, and used mousemotionlistener to detect the mouse clicks, and I want to be able to draw on top of the image. I want to be able to, if the user makes a click, make that pixel a certain color while preserving the rest of the image, however, I couldn't find out how to use Graphics to do so without deleting the rest of the image or opening a new window.

public class Simple extends JFrame{
  static ImageIcon icon;
  static JFrame myframe;
  static JLabel mylabel;
  static BufferedImage image = null;
  public static void main(String[] args) {
    try{
      image = ImageIO.read(new File("mypic.png"));
    }
    catch (IOException e) {
      e.printStackTrace();
    }
    icon=new ImageIcon(image);
    myframe=new JFrame();
    myframe.setSize(200,200);
    myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mylabel=new JLabel();
    mylabel.setIcon(icon);
    myframe.getContentPane().add(mylabel);
    myframe.pack();
    Container container = myframe.getContentPane();
    MouseMotionEvents3 mousemotion = new MouseMotionEvents3();
    container.add(mousemotion);
    myframe.setVisible(true);
    while(1 == 1) {
      if(mousemotion.signal == true) {
        System.out.println("second message");
        mousemotion.signal = false;      
      }
    }
  }
}
  class MouseMotionEvents3 extends JPanel implements MouseListener,
    MouseMotionListener {
    public boolean signal;
    public MouseMotionEvents3() {
      addMouseListener(this);
      addMouseMotionListener(this);
      signal = false;
    }
    public void mouseClicked(MouseEvent me) {
     // System.out.println("i hate you");
    }

    public void mouseEntered(MouseEvent me) {
    }

    public void mouseExited(MouseEvent me) {
    }

    public void mousePressed(MouseEvent me) {
      signal = true;
      System.out.println("message");
    }

    public void mouseReleased(MouseEvent me) {
    }

    public void mouseDragged(MouseEvent me) {
    }

    public void mouseMoved(MouseEvent me) {
    }
  }

I would highly recommend that you start by having a read through Performing Custom Painting and the 2D Graphics Trail , they will provide you with a starting point.

There are a number of ways you might achieve this, this example simply keeps track of the click points and draws dots over the top of the image

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Test {

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

    public Test() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private List<Point> points;
        private BufferedImage image;

        public TestPane() {
            points = new ArrayList<>(25);
            try {
                image = ImageIO.read(new File("/Users/shanewhitehead/Desktop/Screen Shot 2017-03-09 at 1.55.18 pm.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    points.add(e.getPoint());
                    repaint();
                }                
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return image == null ? new Dimension(200, 200) : new Dimension(image.getWidth(), image.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            if (image != null) {
                g2d.drawImage(image, 0, 0, this);
            }
            g2d.setColor(Color.RED);
            for (Point p : points) {
                g2d.fillOval(p.x - 4, p.y - 4, 8, 8);
            }
            g2d.dispose();
        }

    }

}

This example draws the dots directly to the image itself...

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Test {

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

    public Test() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage image;

        public TestPane() {
            try {
                image = ImageIO.read(new File("/Users/shanewhitehead/Desktop/Screen Shot 2017-03-09 at 1.55.18 pm.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (image != null) {
                        Point p = e.getPoint();
                        Graphics2D g2d = image.createGraphics();
                        g2d.setColor(Color.RED);
                        g2d.fillOval(p.x - 4, p.y - 4, 8, 8);
                        g2d.dispose();
                        repaint();
                    }
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return image == null ? new Dimension(200, 200) : new Dimension(image.getWidth(), image.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.drawImage(image, 0, 0, this);
            g2d.dispose();
        }

    }

}

In both cases, they simply make use of the Graphics2D API

The simplest method would be to have a list of points that represent the pixels you wish to colour. Then override the paint method for the label to first call super.paint (to display the image) and then paint the pixels that have been clicked.

List<Point> points = new ArrayList<>();

myLabel = new JLabel() {
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        points.forEach(p -> g.fillRect(p.x, p.y, 1, 1));
    }
};

In your mouse handling just add the current point to the list and repaint the label.

public void mouseClicked(MouseEvent me) {
    points.add(me.getPoint());
    myLabel.repaint();
}

There are more sophisticated methods that involve buffered images but this is likely good enough to get you started.

I figured it out, I can use the getGraphics() method of the JFrame to allow myself to draw on top of the image.

edit: Andrew Thompson is right, minimizing the window removes the changes.

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