如何使用鼠标拖动事件在Java applet上绘制矩形

我正在使用java。 我想基于mousedrag事件绘制矩形。 如果用户拖动鼠标,则applet上的矩形应根据当前鼠标坐标增加或减少。 我有以下代码。

在下面的代码中,我正在使用[b] SelectionArea [/ b]类,它扩展了我正在执行绘图操作的canvas。 我在这个类中使用[b] image [/ b]变量进行双缓冲以减少闪烁并保存applet的先前状态(即绘制applet的内容)

但是如果我绘制第一个矩形,代码工作正常。 如果我开始绘制第二个矩形,则先前绘制的矩形正在消失。 我希望先前绘制的矩形在屏幕上

任何人都可以告诉我如何解决这个问题。

import java.awt.*; import java.applet.Applet; import java.awt.event.*; /* * This displays a framed area. When the user drags within * the area, this program displays a rectangle extending from * where the user first pressed the mouse button to the current * cursor location. */ public class RectangleDemo extends Applet { SelectionArea drawingPanel; Label label; public void init() { GridBagLayout gridBag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); setLayout(gridBag); drawingPanel = new SelectionArea(this); c.fill = GridBagConstraints.BOTH; c.weighty = 1.0; c.gridwidth = GridBagConstraints.REMAINDER; //end row gridBag.setConstraints(drawingPanel, c); add(drawingPanel); label = new Label("Drag within the framed area."); c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1.0; c.weighty = 0.0; gridBag.setConstraints(label, c); add(label); drawingPanel.setVisible(true); validate(); } public void paint(Graphics g){ drawingPanel.repaint(); } public void update(Graphics g){ paint(g); } 

}

 class SelectionArea extends Canvas implements ActionListener, MouseListener, MouseMotionListener{ Rectangle currentRect; RectangleDemo controller; //for double buffering Image image; Graphics offscreen; public SelectionArea(RectangleDemo controller) { super(); this.controller = controller; addMouseListener(this); addMouseMotionListener(this); } public void actionPerformed(ActionEvent ae){ repaintoffscreen(); } public void repaintoffscreen(){ image = createImage(this.getWidth(), this.getHeight()); offscreen = image.getGraphics(); Dimension d = getSize(); if(currentRect != null){ Rectangle box = getDrawableRect(currentRect, d); //Draw the box outline. offscreen.drawRect(box.x, box.y, box.width - 1, box.height - 1); //repaint(); } } public void mouseEntered(MouseEvent me) {} public void mouseExited(MouseEvent me){ } public void mouseClicked(MouseEvent me){} public void mouseMoved(MouseEvent me){} public void mousePressed(MouseEvent me) { currentRect = new Rectangle(me.getX(), me.getY(), 0, 0); repaintoffscreen(); } public void mouseDragged(MouseEvent me) { System.out.println("here in dragged()"); currentRect.setSize(me.getX() - currentRect.x, me.getY() - currentRect.y); repaintoffscreen(); repaint(); } public void mouseReleased(MouseEvent me) { currentRect.setSize(me.getX() - currentRect.x, me.getY() - currentRect.y); repaintoffscreen(); repaint(); } public void update(Graphics g){ paint(g); } public void paint(Graphics g) { g.drawImage(image, 0, 0, this); } Rectangle getDrawableRect(Rectangle originalRect, Dimension drawingArea) { int x = originalRect.x; int y = originalRect.y; int width = originalRect.width; int height = originalRect.height; //Make sure rectangle width and height are positive. if (width < 0) { width = 0 - width; x = x - width + 1; if (x < 0) { width += x; x = 0; } } if (height < 0) { height = 0 - height; y = y - height + 1; if (y  drawingArea.width) { width = drawingArea.width - x; } if ((y + height) > drawingArea.height) { height = drawingArea.height - y; } return new Rectangle(x, y, width, height); } 

}

如果我在全屏模式下运行此代码,那么我发现只有在我释放鼠标后,矩形才会在屏幕上显示。 但我想拖动鼠标时矩形在屏幕上,它应该根据当前鼠标坐标改变它的尺寸。 任何人都可以帮助我。

家庭作业?

基本上你需要做的是:

  1. 在鼠标按下时保持鼠标向下坐标并重新绘制
  2. 在鼠标移动时保持当前鼠标坐标并重新绘制
  3. 在鼠标向上时,取消鼠标向下坐标以指示没有rect,并重新绘制。
  4. 在绘画,绘制背景,然后在mousedown和cur-mouse坐标之间的rect。

如果您不想保留背景图像,可以使用Graphics xor函数进行操作,绘制相同的rect两次将擦除旧的rect,这样您就可以使用它直接在图形对象上恢复旧图像。

编辑:代码xor使用示例:

 public void paint(Graphics g) { g.setXORMode(Color.black); // draw old rect if there is one. this will erase it // draw new rect, this will draw xored g.setDrawMode(); // restore normal draw mode } 

Xor有一个有趣的属性:

 xor(xor(x)) = x 

所以两次相同的像素恢复它的原始颜色。

有几个问题需要解决。

首先,只能绘制一个矩形,这是由于程序的设计。 在您的代码中,每当调用repaintoffscreen方法时, currectRect字段用于绘制矩形。 但是,没有规定要保持过去制作的矩形。

保持过去矩形的一种方法可能是制作另一个字段,例如, List ,用于存储过去的矩形。 然后,释放鼠标时, add当前矩形add到该列表。

然后,为了显示所有矩形, currentRect和过去的矩形, repaintoffscreen不仅需要使用currentRect执行getDrawableRectoffscreen.drawRect ,还需要使用存储在List的过去矩形。 (提示,使用for循环遍历列表。)

其次,关于直到释放鼠标按钮之后才出现的矩形,而不是使用mouseDragged方法,可能使用mouseMoved方法以及检查以查看鼠标按钮被按下可能是一种解决方法。 (我想我以前在处理mouseDragged方法时也遇到了麻烦。)

传入mouseMoved方法的MouseEvent可用于检查getButton方法是否按下按钮:

 public void mouseMoved(MouseEvent e) { // Check if button1 is pressed. if (e.getButton() == MouseEvent.BUTTON1) { // Perform sizing of rectangle and off-screen drawing, and repaint. } } 

我的问题是关于创建一个选择矩形反转鼠标点击位置,但最后我用这个方法做了这个:

 ... //to set the selection area private int iniSelX; private int iniSelY; private int endSelX; private int endSelY; private JPanel myJPanel = new JPanel() { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.WHITE); g.fillRect(0, 0, this.getWidth(), this.getHeight()); g.setColor(Color.red); g.drawLine(260, 5, 260, 260); g.setColor(Color.BLUE); //verify if go draw the rectangle if (iniSelX != 0 || endSelX != 0) { boolean revertX = iniSelX < endSelX; boolean revertY = iniSelY < endSelY; //Simple way //g.drawRect(iniSelX, iniSelY, endSelX - iniSelX, endSelY - iniSelY); //reverse way g.drawRect(revertX ? iniSelX : endSelX, revertY ? iniSelY : endSelY, revertX ? endSelX - iniSelX : iniSelX - endSelX, revertY ? endSelY - iniSelY : iniSelY - endSelY); } } }; ... addMouseMotionListener(new MouseMotionListener() { @Override public void mouseDragged(MouseEvent m) { //update selection area endSelX = m.getX(); endSelY = m.getY(); repaint(); } @Override public void mouseMoved(MouseEvent m) { repaint(); } }); addMouseListener(new MouseListener() { ... @Override public void mousePressed(MouseEvent e) { //start drawing the selection iniSelX = e.getX() - 15; iniSelY = e.getY() - 20; } @Override public void mouseReleased(MouseEvent e) { //start drawing the selection iniSelX = 0; iniSelY = 0; endSelX = 0; endSelY = 0; } ... }); } public void log() { System.out.println("iniSelX" + iniSelX); System.out.println("iniSelY" + iniSelY); System.out.println("endSelX" + endSelX); System.out.println("endSelY" + endSelY); } ... 

我希望这很有用。