在 JPanel 中在图像上绘制形状

2022-01-24 00:00:00 image java swing paintcomponent jframe

我需要在 JPanel 的 JLabel 中显示的图像上绘制形状(圆形或自由线).

I need to draw shapes (circle or free line) over an image that is shown in a JLabel of a JPanel.

我的代码基于问题 如何在拖动光标时绘制没有间隙的细线? 和 单击 2 次鼠标画一个圆.

I based my code on the questions How to draw thin line with no gap while dragging the cursor? and Draw a circle using 2 mouse clicks.

代码如下.问题是,当我开始绘制图像时,图像会消失,只有在我停止后才会重新出现.如果我评论 super.paintComponent(g); 行,那不会发生,但是当我画圆时,它会保持先前位置的路径.

The code is bellow. The problem is that when I start drawing the image disappears and only reappears after I stop. If I comment the line super.paintComponent(g); that doesnt happen but when I draw the circle it maintains a path of the previous positions.

public static void main(String args[]) {
try {
    URL url = new URL("http://www.senhoritatours.com/wp-content/uploads/2014/05/Porto-.jpg");
  backgroundImage = ImageIO.read(url);
} catch (Exception e) {
  e.printStackTrace();
}

loadAnnotation();
loadBackground();

JFrame f;
f = new JFrame();
f.setLayout(new BorderLayout());
f.add(mp);
f.pack();
f.setVisible(true);

}

/* 第 0 层:* 加载背景图片 */

/* Layer 0: * Load background picture */

public static void loadBackground() {

  JLabel lbImg = new JLabel();
    lbImg.setBounds(0, 0, new ImageIcon(backgroundImage).getIconWidth(), new ImageIcon(backgroundImage).getIconHeight());
    lbImg.setIcon(new ImageIcon(backgroundImage));

  mp = new JPanel(new BorderLayout());


btnCircle.addActionListener(new ActionListener() {
  @Override
  public void actionPerformed(ActionEvent ae) {

      if(btnCircle.isEnabled())
      {
          btnCircle.setEnabled(false);
          btnLine.setEnabled(true);
      }
  }
});



btnLine.setEnabled(true);
btnCircle.setEnabled(false);

btnLine.addActionListener(new ActionListener() {
  @Override
  public void actionPerformed(ActionEvent ae) {

      if(btnLine.isEnabled())
      {
          btnLine.setEnabled(false);
          btnCircle.setEnabled(true);
      }
  }
});



 mp.add(btnCircle);
 mp.add(btnLine);    
 mp.add(lbImg);
 mp.add(p);

}

/* 第 1 层:* 注释:在背景图片上绘制任何东西!*/

/* Layer 1: * Annotation: Draw on top of background picture anything! */

  public static void loadAnnotation() {

p = new JPanel() {
  public void paintComponent(Graphics g) {
      super.paintComponent(g);

      Graphics2D g2 = (Graphics2D)g;

    g2.setColor(Color.RED);
    if (_bufImage == null) {
        int w = this.getWidth();
        int h = this.getHeight();
        _bufImage  = new BufferedImage(1024,600, BufferedImage.TRANSLUCENT);
        Graphics2D gc = _bufImage.createGraphics();
    }

    g2.drawImage(_bufImage, null, 0, 0);
    if (_state == State.DRAGGING) {

        if (!btnLine.isEnabled())
        { 

            g.drawLine(_start.x, _start.y, _end.x  , _end.y);
        }

    }



    if (!btnCircle.isEnabled())
    {

        g.drawOval(x, y, width, height);

    }


  }

  public Dimension getPreferredSize() {
    return new Dimension(1024, 600);
  }
};

p.setLayout(new OverlayLayout(p));

p.addMouseListener(new MouseListener() {
  @Override
  public void mouseClicked(MouseEvent me) {

  }

  @Override
  public void mousePressed(MouseEvent me) {

      last = me.getPoint();
      dragging = isInsideEllipse(last);
      if (!dragging) {
          x = last.x;
          y = last.y;
          width = 0;
          height = 0;
      }

    p.repaint();
  }

  @Override
  public void mouseReleased(MouseEvent me) {
    //_state = State.IDLE;

      last = null;
      dragging = false;

    _state = State.IDLE;
    p.repaint();
  }

  @Override
  public void mouseEntered(MouseEvent me) {
  }

  @Override
  public void mouseExited(MouseEvent me) {
  }
});

p.addMouseMotionListener(new MouseMotionListener() {


  @Override
  public void mouseDragged(MouseEvent me) {

      if(!btnLine.isEnabled())
      {
          _state = State.DRAGGING;
            _end   = me.getPoint();
            if (_state == State.DRAGGING) {
                Graphics2D g2 = _bufImage.createGraphics();
                g2.setColor(Color.red);
                g2.setStroke(new BasicStroke(2));
                g2.drawLine(_start.x, _start.y, _end.x, _end.y);
                p.repaint();

                //
            }
            _start = _end;
      }
      else
      {


          int dx = me.getX() - last.x;
          int dy = me.getY() - last.y;

            if (dragging) {
                x += dx;
                y += dy;

            } else {
                width += dx;
                height += dy;
            }
            last = me.getPoint();

            p.repaint();
      }


  }

  @Override
  public void mouseMoved(MouseEvent me) {
    //System.out.println("move");
    _start = me.getPoint();

  }
});
}

推荐答案

要么

  1. 通过 Graphics#drawImage(...) 以与您进行绘图相同的 paintComponent 方法显示图像.您可以在 super.paintComponent(g) 调用之后立即调用它.
  2. 或者在显示图像的 JLabel 的 paintComponent(...) 方法中进行绘图.
  1. Display the image in the same paintComponent method that you're doing your drawing in, via Graphics#drawImage(...). You would call this immediately after the super.paintComponent(g) call.
  2. Or do your drawing in the paintComponent(...) method of your JLabel, the one displaying the image.

<小时>

例如:

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.*;

@SuppressWarnings("serial")
public class DrawingPanel extends JPanel {
   private final static String PATH = "https://upload.wikimedia.org/wikipedia/commons/"
         + "thumb/7/7c/Thomas_Hicks_-_Leopold_Grozelier_-_Presidential_Candidate_"
         + "Abraham_Lincoln_1860_-_cropped_to_lithographic_plate.jpg/"
         + "463px-Thomas_Hicks_-_Leopold_Grozelier_-_Presidential_Candidate_"
         + "Abraham_Lincoln_1860_-_cropped_to_lithographic_plate.jpg";
   private static final Color DRAWING_COLOR = new Color(255, 100, 200);
   private static final Color FINAL_DRAWING_COLOR = Color.red;

   private BufferedImage backgroundImg;
   private Point startPt = null;
   private Point endPt = null;
   private Point currentPt = null;
   private int prefW;
   private int prefH;

   public DrawingPanel() throws IOException {
      URL imgUrl = new URL(PATH);
      BufferedImage bImg = ImageIO.read(imgUrl);
      prefW = bImg.getWidth();
      prefH = bImg.getHeight();
      backgroundImg = new BufferedImage(prefW, prefH,
            BufferedImage.TYPE_INT_ARGB);
      Graphics g = backgroundImg.getGraphics();
      g.drawImage(bImg, 0, 0, this);
      g.dispose();

      MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
      addMouseMotionListener(myMouseAdapter);
      addMouseListener(myMouseAdapter);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (backgroundImg != null) {
         g.drawImage(backgroundImg, 0, 0, this);
      }

      if (startPt != null && currentPt != null) {
         g.setColor(DRAWING_COLOR);
         int x = Math.min(startPt.x, currentPt.x);
         int y = Math.min(startPt.y, currentPt.y);
         int width = Math.abs(startPt.x - currentPt.x);
         int height = Math.abs(startPt.y - currentPt.y);
         g.drawRect(x, y, width, height);
      }
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(prefW, prefH);
   }

   public void drawToBackground() {
      Graphics g = backgroundImg.getGraphics();
      g.setColor(FINAL_DRAWING_COLOR);
      int x = Math.min(startPt.x, endPt.x);
      int y = Math.min(startPt.y, endPt.y);
      int width = Math.abs(startPt.x - endPt.x);
      int height = Math.abs(startPt.y - endPt.y);
      g.drawRect(x, y, width, height);
      g.dispose();

      startPt = null;
      repaint();
   }

   private class MyMouseAdapter extends MouseAdapter {
      @Override
      public void mouseDragged(MouseEvent mEvt) {
         currentPt = mEvt.getPoint();
         DrawingPanel.this.repaint();
      }

      @Override
      public void mouseReleased(MouseEvent mEvt) {
         endPt = mEvt.getPoint();
         currentPt = null;
         drawToBackground();
      }

      @Override
      public void mousePressed(MouseEvent mEvt) {
         startPt = mEvt.getPoint();
      }
   }

   private static void createAndShowGui() {
      DrawingPanel mainPanel = null;
      try {
         mainPanel = new DrawingPanel();
      } catch (IOException e) {
         e.printStackTrace();
         System.exit(-1);
      }

      JFrame frame = new JFrame("Drawing Panel");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

相关文章