如何使用鼠标拖动事件在java小程序上绘制矩形

发布于 2024-07-21 03:02:11 字数 4160 浏览 7 评论 0原文

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

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

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

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

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);
}

如果我在全屏模式下运行此代码,那么我会看到只有在释放鼠标后矩形才会出现在屏幕上。 但我希望在拖动鼠标时矩形出现在屏幕上,并且它应该根据当前鼠标坐标更改其尺寸。 任何人都可以帮助我吗?

i am using java.
i want to draw rectangle based on mousedrag event. if user dragging the mouse, then the rectangle on the applet should increase or decrease basing on current mouse coordinates.
i have the following code.

in the following code i am using [b]SelectionArea[/b] class which extends a canvas on which i am performing drawing operation. i am using [b]image[/b] variable in this class for double buffering to reduce flickering and to save the applet's previous state(i.e drawing content of applet)

but the code is working fine if i draw first rectangle. if i start to draw second rectangle the previously drawn rectangle is disappearing. i want the previously drawn rectangle to be on the screen

can any one tell me how to solve this.

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);
}

}

also if i run this code on full screen mode then i am seeing that the rectangle is appering on screen only after i released the mouse. but i want the rectangle to be on the screen while dragging the mouse and it should change it's dimension according to the current mouse coordinates.
can any one help me pls.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

荒人说梦 2024-07-28 03:02:11

家庭作业?

基本上你需要做的是:

  1. 鼠标按下时保持鼠标按下坐标并
  2. 在鼠标移动时重新绘制保持当前鼠标坐标并
  3. 在鼠标向上时重新绘制,使鼠标按下坐标无效以指示没有矩形,然后重新绘制。
  4. 在绘画上,绘制背景,然后在鼠标按下和当前鼠标坐标之间进行调整。

如果你不想保留背景图像,你可以使用 Graphics 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(x)) = x

因此对同一像素进行异或两次可以恢复其原始颜色。

homework?

basically what you need to do is:

  1. on mouse down keep the mouse-down coordinates and repaint
  2. on mouse move keep current mouse coordinates and repaint
  3. on mouse up, nullify the mouse-down coordinates to indicate there is no rect, and repaint.
  4. on paint, draw background and then rect between mousedown and cur-mouse coordinates.

if you don't want to keep a background image, you can do a trick with the Graphics xor function, drawing the same rect twice will erase the old rect, so you can use it to restore the old image straight on the graphics object.

Edit: code xor usage sample:

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 has the an interesting property:

xor(xor(x)) = x

so xoring the same pixel twice restores it's original color.

墨洒年华 2024-07-28 03:02:11

有几个问题需要解决。

首先,关于只能绘制一个矩形,这是由于您的程序设计所致。 在您的代码中,每当调用 repaintoffscreen 方法时,都会使用 currectRect 字段来绘制矩形。 然而,没有规定可以保留过去制作的矩形。

保存过去的矩形的一种方法可能是创建另一个字段,例如,用于存储过去的矩形的List。 然后,当释放鼠标时,将当前矩形添加到该列表中。

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

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

MouseEvent 传递到 mouseMoved 方法可用于检查按钮是否已按下被 郁闷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.
    }
}

There are a couple issues that need to be addressed.

First, regarding only one rectangle can be drawn, this is due to the design of your program. In your code, whenever the repaintoffscreen method is called, the currectRect field is used to draw a rectangle. However, there is no provision to keep holding onto rectangles which were made in the past.

One way to keep a hold of past rectangles would be perhaps to make another field which is, for example, a List<Rectangle> which is used to store past rectangles. Then, when the mouse is released, add the current rectangle to that list.

Then, in order for all rectangles, currentRect and past rectangles to appear, repaintoffscreen will need to not only perform getDrawableRect and offscreen.drawRect using the currentRect but also with the past rectangles which are stored in the List<Rectangle>. (Hint, use a for loop to iterate through the list.)

Second, regarding the rectangle not appearing until after releasing the mouse button, rather than using the mouseDragged method, maybe using the mouseMoved method along with a check to see that the mouse button is depressed may be a workaround. (I think I've also had trouble dealing with the mouseDragged method in the past.)

The MouseEvent passed into the mouseMoved method can be used to check if a button is depressed by the getButton method:

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.
    }
}
北方的韩爷 2024-07-28 03:02:11

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

...     //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);
    } ...

我希望这很有用。

My question was about create a select rectangle invert mouse click position, but, in the end I got make this with this method:

...     //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);
    } ...

I hope this is useful.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文