我有一个绘制绘图的Java应用程序。我想让用户可以用鼠标标记区域(例如,为了放大它)。 为此我使用MouseMotionListener类,当鼠标被(单击然后)移动时,我保存当前所选的位置(它不是最终的,因为用户没有释放鼠标)矩形,并使用{ {1}}功能。我希望在原始图形上显示该矩形,使其类似于MSPaint中的选择工具。
问题在于,当我调用repaint()
函数时,调用方法repaint()
,其中我使用删除绘图的方法paintComponent (Graphics page)
。但是,如果当我知道用户正在选择一个矩形时我不使用该方法,我会得到所有选定的矩形一个在另一个上面“打包”,这是一个不理想的结果 - 我希望显示当前选中的只有矩形。
我以为我应该能够保存图形图形页面的副本,并在每次用户移动鼠标时以某种方式恢复它,但我找不到任何有用方法的文档。
非常感谢,
罗恩。
编辑:以下是我的代码的相关部分:
super.paintComponent(page)
答案 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
方法中,清除图形并使用支架中的坐标绘制一个矩形。这是基本的想法。
更新:如何在现有图像的顶部绘制新形状: 我想到两个选择:
paint
上绘制所有这些形状坐标。优点:当形状很少时很好,允许撤消。缺点:当形状数量增加时,paint
方法将在每次传递中花费越来越多的时间。paint
调用时,首先绘制图像,然后在顶部绘制当前活动的形状。当活动形状持久化时(onMouseReleased),它将保存到背景图像中。优点:高效,恒定的时间。缺点:在每次鼠标移动时绘制一个大背景图像可能是“昂贵的”。