在现有图形页面上绘制一个矩形

时间:2011-10-19 13:40:12

标签: java swing

我有一个绘制绘图的Java应用程序。我想让用户可以用鼠标标记区域(例如,为了放大它)。 为此我使用MouseMotionListener类,当鼠标被(单击然后)移动时,我保存当前所选的位置(它不是最终的,因为用户没有释放鼠标)矩形,并使用{ {1}}功能。我希望在原始图形上显示该矩形,使其类似于MSPaint中的选择工具。

问题在于,当我调用repaint()函数时,调用方法repaint(),其中我使用删除绘图的方法paintComponent (Graphics page)。但是,如果当我知道用户正在选择一个矩形时我不使用该方法,我会得到所有选定的矩形一个在另一个上面“打包”,这是一个不理想的结果 - 我希望显示当前选中的只有矩形。

我以为我应该能够保存图形图形页面的副本,并在每次用户移动鼠标时以某种方式恢复它,但我找不到任何有用方法的文档。

非常感谢,

罗恩。

编辑:以下是我的代码的相关部分:

super.paintComponent(page)

2 个答案:

答案 0 :(得分:4)

我打赌您通过对组件的getGraphics()调用来获取Graphics对象,并且不满意,因为这会获得一个不会持久存在的Graphics对象。出于这个原因,你不应该这样做,而只是在JPanel的paintComponent中进行绘图。如果你这样做,一切都会很开心。

顺便一提 - 如果您告诉我们更多关于您的问题的相关细节,例如您如何获取Graphics对象以及您是如何使用它绘制的,我们将能够更好地帮助您,关键问题在这里。否则,我们只能对您正在尝试做的事情进行猜测。

如,

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;

public class MandelDraw extends JPanel {
private static final String IMAGE_ADDR = "http://upload.wikimedia.org/" +
        "wikipedia/commons/thumb/b/b3/Mandel_zoom_07_satellite.jpg/" +
        "800px-Mandel_zoom_07_satellite.jpg";
private static final Color DRAWING_RECT_COLOR = new Color(200, 200, 255);
private static final Color DRAWN_RECT_COLOR = Color.blue;

   private BufferedImage image;
   private Rectangle rect = null;
   private boolean drawing = false;

   public MandelDraw() {
      try {
         image = ImageIO.read(new URL(IMAGE_ADDR));
         MyMouseAdapter mouseAdapter = new MyMouseAdapter();
         addMouseListener(mouseAdapter);
         addMouseMotionListener(mouseAdapter);
      } catch (MalformedURLException e) {
         e.printStackTrace();
         System.exit(-1);
      } catch (IOException e) {
         e.printStackTrace();
         System.exit(-1);
      }
   }

   @Override
   public Dimension getPreferredSize() {
      if (image != null) {
         return new Dimension(image.getWidth(), image.getHeight());
      }
      return super.getPreferredSize();
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D)g;
      if (image != null) {
         g.drawImage(image, 0, 0, null);
      }
      if (rect == null) {
         return;
      } else if (drawing) {
         g2.setColor(DRAWING_RECT_COLOR);
         g2.draw(rect);
      } else {
         g2.setColor(DRAWN_RECT_COLOR);
         g2.draw(rect);
      }
   }

   private class MyMouseAdapter extends MouseAdapter {
      private Point mousePress = null; 
      @Override
      public void mousePressed(MouseEvent e) {
         mousePress = e.getPoint();
      }

      @Override
      public void mouseDragged(MouseEvent e) {
         drawing = true;
         int x = Math.min(mousePress.x, e.getPoint().x);
         int y = Math.min(mousePress.y, e.getPoint().y);
         int width = Math.abs(mousePress.x - e.getPoint().x);
         int height = Math.abs(mousePress.y - e.getPoint().y);

         rect = new Rectangle(x, y, width, height);
         repaint();
      }

      @Override
      public void mouseReleased(MouseEvent e) {
         drawing = false;
         repaint();
      }

   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("MandelDraw");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new MandelDraw());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

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

答案 1 :(得分:1)

您需要在每次鼠标移动时重新绘制:

    public void mouseDragged(MouseEvent e){
        int x = e.getX();
        int y = e.getY();
        //Update the rectangle holder object with that point coordinates
        repaint();
    }

您可能有一个持有人矩形对象来保存初始和最终矩形点。在鼠标单击时设置首字母,最后在鼠标拖动和鼠标释放时修改。

paint方法中,清除图形并使用支架中的坐标绘制一个矩形。这是基本的想法。

更新:如何在现有图像的顶部绘制新形状: 我想到两个选择:

  1. 如果您只绘制形状(例如线条,矩形和其他Java2D内容),您可以拥有一个包含这些形状坐标的Collection,并在每个paint上绘制所有这些形状坐标。优点:当形状很少时很好,允许撤消。缺点:当形状数量增加时,paint方法将在每次传递中花费越来越多的时间。
  2. 拥有“背景图片”。在每次paint调用时,首先绘制图像,然后在顶部绘制当前活动的形状。当活动形状持久化时(onMouseReleased),它将保存到背景图像中。优点:高效,恒定的时间。缺点:在每次鼠标移动时绘制一个大背景图像可能是“昂贵的”。