Как нарисовать прямоугольник на Java-апплет, используя событие перетаскивания мыши - PullRequest
2 голосов
/ 19 мая 2009

Я использую 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);
}

}

также, если я запускаю этот код в полноэкранном режиме, то вижу, что прямоугольник появляется на экране только после того, как я отпустил мышь. но я хочу, чтобы при перетаскивании мыши на экране был прямоугольник, и он должен изменить размер в соответствии с текущими координатами мыши. Может ли кто-нибудь помочь мне, пожалуйста.

Ответы [ 3 ]

3 голосов
/ 19 мая 2009

домашнее задание?

В основном вам нужно сделать следующее:

  1. при наведении мыши удерживайте координаты мыши и перекрасьте
  2. при перемещении мыши сохраняйте текущие координаты мыши и перекрашивайте
  3. при наведении курсора мыши, обнулить координаты при наведении курсора мыши, чтобы указать, что прямоугольника нет, и перекрасить.
  4. на краске, нарисуйте фон и затем наведите прямоугольник между координатами мыши и курсора мыши.

если вы не хотите сохранять фоновое изображение, вы можете сделать трюк с функцией Graphics xor, дважды нарисовав один и тот же прямоугольник, стереть старый прямоугольник, чтобы вы могли использовать его для восстановления старого изображения прямо на графический объект.

Редактировать: пример использования кода 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

, поэтому ксероксация одного и того же пикселя дважды восстанавливает его первоначальный цвет.

0 голосов
/ 18 января 2013

Мой вопрос был о том, чтобы создать выделенную прямоугольную инвертированную позицию щелчка мышью, но, в конце концов, я получил это следующим способом:

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

Надеюсь, это полезно.

0 голосов
/ 19 мая 2009

Есть пара вопросов, которые необходимо решить.

Во-первых, можно нарисовать только один прямоугольник, это связано с дизайном вашей программы. В вашем коде всякий раз, когда вызывается метод repaintoffscreen, поле currectRect используется для рисования прямоугольника. Тем не менее, нет никаких положений, чтобы продолжать держаться за прямоугольники, которые были сделаны в прошлом.

Один из способов сохранить прошлые прямоугольники - это создать другое поле, например, List<Rectangle>, которое используется для хранения прошлых прямоугольников. Затем, когда мышь отпущена, add текущий прямоугольник в этот список.

Затем, чтобы появились все прямоугольники, currentRect и прошлые прямоугольники, repaintoffscreen потребуется не только выполнить getDrawableRect и offscreen.drawRect с использованием currentRect, но и с прошлыми прямоугольниками, которые сохранены в List<Rectangle>. (Подсказка, используйте цикл 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.
    }
}
...