如何使用鼠标拖动事件在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); }
}
如果我在全屏模式下运行此代码,那么我发现只有在我释放鼠标后,矩形才会在屏幕上显示。 但我想拖动鼠标时矩形在屏幕上,它应该根据当前鼠标坐标改变它的尺寸。 任何人都可以帮助我。
家庭作业?
基本上你需要做的是:
- 在鼠标按下时保持鼠标向下坐标并重新绘制
- 在鼠标移动时保持当前鼠标坐标并重新绘制
- 在鼠标向上时,取消鼠标向下坐标以指示没有rect,并重新绘制。
- 在绘画,绘制背景,然后在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
执行getDrawableRect
和offscreen.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); } ...
我希望这很有用。