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

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

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

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

非常感谢你,

罗恩。

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

 public class DrawingPanel extends JPanel { public FractalPanel() { addMouseListener (new MyListener()); addMouseMotionListener (new MyListener()); setBackground (Color.black); setPreferredSize (new Dimension(200,200)); setFocusable(true); } public void paintComponent (Graphics page) { super.paintComponent(page); //that's where the drawing takes place: page.setColor(Color.red), page.drawOval(..) etc } private class MyListener implements MouseListener, MouseMotionListener { ... public void mouseDragged (MouseEvent event) { //saving the location of the rectangle isHoldingRectangle = true; repaint(); } } } 

我打赌你通过组件上的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://sofzh.miximages.com/java/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(); } }); } } 

您需要重新绘制每个鼠标移动:

  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),它将保存到背景图像中。 优点:高效,恒定的时间。 缺点:在每次鼠标移动时绘制一个大的背景图像可能是“昂贵的”。