我正在使用java。 我想基于mousedrag事件绘制矩形。如果用户拖动鼠标,则applet上的矩形应根据当前鼠标坐标增加或减少。 我有以下代码。
在下面的代码中我正在使用[b] SelectionArea [/ b]类,它扩展了我正在执行绘图操作的画布。我在这个类中使用[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 < 0) {
height += y;
y = 0;
}
}
//The rectangle shouldn't extend past the drawing area.
if ((x + width) > drawingArea.width) {
width = drawingArea.width - x;
}
if ((y + height) > drawingArea.height) {
height = drawingArea.height - y;
}
return new Rectangle(x, y, width, height);
}
}
如果我在全屏模式下运行此代码,那么我发现只有在我释放鼠标后,矩形才会出现在屏幕上。但是我希望拖动鼠标时矩形在屏幕上,它应该根据当前鼠标坐标改变它的尺寸。 任何人都可以帮助我。
答案 0 :(得分:3)
功课?
基本上你需要做的是:
如果您不想保留背景图像,可以使用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
因此,对同一像素进行两次修复会恢复原始颜色。
答案 1 :(得分:0)
有几个问题需要解决。
首先,只能绘制一个矩形,这是由于程序的设计。在您的代码中,每当调用repaintoffscreen
方法时,currectRect
字段用于绘制矩形。但是,没有规定要保持过去制作的矩形。
保持过去矩形的一种方法可能是制作另一个字段,例如,List<Rectangle>
用于存储过去的矩形。然后,当鼠标被释放时,add
当前矩形到该列表。
然后,为了显示所有矩形,currentRect
和过去的矩形,repaintoffscreen
不仅需要使用{{1}执行getDrawableRect
和offscreen.drawRect
而且还有过去存储在currentRect
中的矩形。 (提示,使用List<Rectangle>
循环遍历列表。)
其次,关于矩形在释放鼠标按钮之后才出现,而不是使用for
方法,可能使用mouseDragged
方法以及检查鼠标按钮是否被按下可能是一种解决方法。 (我想我过去在处理mouseMoved
方法时也遇到了麻烦。)
传入mouseDragged
方法的MouseEvent
可用于检查getButton
方法是否按下按钮:
mouseMoved
答案 2 :(得分:0)
我的问题是关于创建一个选择矩形反转鼠标点击位置,但最后我用这个方法做了这个:
... //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);
} ...
我希望这很有用。