Вопрос по drawing, swing, java, mouseevent – Как нарисовать прямоугольник на Java-апплете с помощью события перетаскивания мышью и сделать так, чтобы он оставался

3

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

package pracpapp2;


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class MouseTracker4July extends JFrame
   implements MouseListener, MouseMotionListener {


  private static final long serialVersionUID = 1L;
  private JLabel mousePosition;
  int x, y;
  int x1, x2, y1, y2;
  int w, h;
  private JLabel recStart;
  private JLabel recStop;
  private JLabel cords;
   // set up GUI and register mouse event handlers
   public MouseTracker4July()
   {
      super( "Rectangle Drawer" );

      mousePosition = new JLabel();
      mousePosition.setHorizontalAlignment(SwingConstants.CENTER);
      getContentPane().add( mousePosition, BorderLayout.CENTER );


      JLabel text1 = new JLabel();
      text1.setText( "At the center the mouse pointer's coordinates will be displayed." );
      getContentPane().add( text1, BorderLayout.SOUTH );

      recStart = new JLabel();
      getContentPane().add(recStart, BorderLayout.WEST);

      recStop = new JLabel();
      getContentPane().add(recStop, BorderLayout.EAST);

      cords = new JLabel();
      getContentPane().add(cords, BorderLayout.NORTH);


      addMouseListener( this );        // listens for own mouse and
      addMouseMotionListener( this );  // mouse-motion events

      setSize( 800, 600 );
      setVisible( true );
   }

   // MouseListener event handlers
   // handle event when mouse released immediately after press
   public void mouseClicked( MouseEvent event )
   {
      mousePosition.setText( "Clicked at [" + event.getX() +
         ", " + event.getY() + "]" );
   }

   // handle event when mouse pressed
   public void mousePressed( MouseEvent event )
   {

      mousePosition.setText( "Pressed at [" +(x1 = event.getX()) +
         ", " + (y1 = event.getY()) + "]" );

      recStart.setText( "Start:  [" + x1 +
         ", " + y1 + "]" );
   }

   // handle event when mouse released after dragging
   public void mouseReleased( MouseEvent event )
   {
     mousePosition.setText( "Released at [" +(x2 = event.getX()) +
         ", " + (y2 = event.getY()) + "]" );

     recStop.setText( "End:  [" + x2 +
         ", " + y2 + "]" );

   }

   // handle event when mouse enters area
   public void mouseEntered( MouseEvent event )
   {
      mousePosition.setText( "Mouse entered at [" + event.getX() +
         ", " + event.getY() + "]" );
   }

   // handle event when mouse exits area
   public void mouseExited( MouseEvent event )
   {
      mousePosition.setText( "Mouse outside window" );
   }

   // MouseMotionListener event handlers
   // handle event when user drags mouse with button pressed
   public void mouseDragged( MouseEvent event )
   {
      mousePosition.setText( "Dragged at [" + (x = event.getX()) + 
         ", " + (y = event.getY()) + "]" );
      // call repaint which calls paint
      repaint();

   }

   // handle event when user moves mouse
   public void mouseMoved( MouseEvent event )
   {
      mousePosition.setText( "Moved at [" + event.getX() +
         ", " + event.getY() + "]" );
   }

   public void paint(Graphics g)
   {
      super.paint(g); // clear the frame surface
      g.drawString("Start Rec Here", x1, y1);
      g.drawString("End Rec Here", x, y);

      w = x1 - x;
      h = y1 - y;
      w = w * -1;
      h = h * -1;

      g.drawRect(x1, y1, w, h);

      cords.setText( "w = " + w + ", h = " + h);
   }

   public static void main( String args[] )
   { 
      MouseTracker4July application = new MouseTracker4July();
      application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
   }

} // end class MouseTracker

Ваш Ответ

4   ответа
4

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

Также вам нужно добавить перерисовку для каждого из ваших событий мыши.

Например: (предполагается, что вы хотите сохранить ВСЕ прямоугольники) - вы можете использовать один прямоугольник, удалив массив и заменив его единственным экземпляром прямоугольника.

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;

public class MouseTracker4July extends JFrame implements MouseListener, MouseMotionListener {

    private static final long serialVersionUID = 1L;
    private final JLabel mousePosition;
    int x1, x2, y1, y2;
    int w, h;
    private final JLabel recStart;
    private final JLabel recStop;
    private final JLabel cords; // set up GUI and register mouse event handlers
    private final ArrayList< Rectangle > rectangles = new ArrayList< Rectangle >();
    private boolean isNewRect = true;

    public MouseTracker4July() {
        super( "Rectangle Drawer" );

        this.mousePosition = new JLabel();
        this.mousePosition.setHorizontalAlignment( SwingConstants.CENTER );
        getContentPane().add( this.mousePosition, BorderLayout.CENTER );

        JLabel text1 = new JLabel();
        text1.setText( "At the center the mouse pointer's coordinates will be displayed." );
        getContentPane().add( text1, BorderLayout.SOUTH );

        this.recStart = new JLabel();
        getContentPane().add( this.recStart, BorderLayout.WEST );

        this.recStop = new JLabel();
        getContentPane().add( this.recStop, BorderLayout.EAST );

        this.cords = new JLabel();
        getContentPane().add( this.cords, BorderLayout.NORTH );

        addMouseListener( this ); // listens for own mouse and
        addMouseMotionListener( this ); // mouse-motion events

        setSize( 800, 600 );
        setVisible( true );

    }

// MouseListener event handlers // handle event when mouse released immediately after press 
    public void mouseClicked( final MouseEvent event ) {
        this.mousePosition.setText( "Clicked at [" + event.getX() + ", " + event.getY() + "]" );

        repaint();
    }

// handle event when mouse pressed 
    public void mousePressed( final MouseEvent event ) {

        this.mousePosition.setText( "Pressed at [" + ( this.x1 = event.getX() ) + ", " + ( this.y1 = event.getY() ) + "]" );

        this.recStart.setText( "Start:  [" + this.x1 + ", " + this.y1 + "]" );

        repaint();
    }

// handle event when mouse released after dragging 
    public void mouseReleased( final MouseEvent event ) {
        this.mousePosition.setText( "Released at [" + ( this.x2 = event.getX() ) + ", " + ( this.y2 = event.getY() ) + "]" );

        this.recStop.setText( "End:  [" + this.x2 + ", " + this.y2 + "]" );

        Rectangle rectangle = getRectangleFromPoints();

        this.rectangles.add( rectangle );

        this.w = this.h = this.x1 = this.y1 = this.x2 = this.y2 = 0;
        this.isNewRect = true;

        repaint();
    }

    private Rectangle getRectangleFromPoints() {
        int width = this.x1 - this.x2;
        int height = this.y1 - this.y2;
        Rectangle rectangle = new Rectangle( width < 0 ? this.x1
            : this.x2, height < 0 ? this.y1
            : this.y2, Math.abs( width ), Math.abs( height ) );

        return rectangle;
    }

// handle event when mouse enters area 
    public void mouseEntered( final MouseEvent event ) {
        this.mousePosition.setText( "Mouse entered at [" + event.getX() + ", " + event.getY() + "]" );
        repaint();
    }

// handle event when mouse exits area 
    public void mouseExited( final MouseEvent event ) {
        this.mousePosition.setText( "Mouse outside window" );
        repaint();
    }

// MouseMotionListener event handlers // handle event when user drags mouse with button pressed 
    public void mouseDragged( final MouseEvent event ) {
        this.mousePosition.setText( "Dragged at [" + ( this.x2 = event.getX() ) + ", " + ( this.y2 = event.getY() ) + "]" ); // call repaint which calls paint repaint();

        this.isNewRect = false;

        repaint();
    }

// handle event when user moves mouse 
    public void mouseMoved( final MouseEvent event ) {
        this.mousePosition.setText( "Moved at [" + event.getX() + ", " + event.getY() + "]" );
        repaint();
    }

    @Override
    public void paint( final Graphics g ) {
        super.paint( g ); // clear the frame surface 
        g.drawString( "Start Rec Here", this.x1, this.y1 );
        g.drawString( "End Rec Here", this.x2, this.y2 );

        Rectangle newRectangle = getRectangleFromPoints();
        if ( !this.isNewRect ) {
            g.drawRect( newRectangle.x, newRectangle.y, newRectangle.width, newRectangle.height );
        }

        for( Rectangle rectangle : this.rectangles ) {
            g.drawRect( rectangle.x, rectangle.y, rectangle.width, rectangle.height );
        }

        this.cords.setText( "w = " + this.w + ", h = " + this.h );

    }

    public static void main( final String args[] ) {
        MouseTracker4July application = new MouseTracker4July();
        application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    }

} // end class MouseTracker
@Tyler: посмотрите на пример, который я разместил. У него есть массив списков прямоугольников для рисования - это позволит хранить прямоугольники. Если вы хотите только 1 прямоугольник, избавьтесь от списка и оставьте один прямоугольник. ИЛИ - вы можете оставить только элементы x, y, w, h - зависит от того, что вы хотите сделать.
Я впервые программирую графически. Как я мог хранить весь прямоугольник. У меня уже есть части прямоугольника (x, y, w, h), сохраненные как int, затем прямоугольник рисуется, но мои целые числа постоянно обновляются, я не уверен, как сохранить их во что-то статическое, что может проводиться на холсте. Tyler
Спасибо, я проверил ваш пример, я знаю, что он работает, я просто пытаюсь выяснить, как все работает (новый Java-программист). В любом случае, я ценю помощь, но уже поздно, и код начинает растапливать мой мозг. Я сделаю это завтра. Еще раз спасибо. Tyler
Настраиваемое рисование должно выполняться на JPanel или JComponent, а не на реальном JFrame, а метод paintComponent () должен быть переопределен, а не метод paint ().
@camickr - я согласен, но ради понимания проблемы я не знаю, поможет ли это Тайлеру в этом (в конечном счете, да).
1

Читайте на этих двухИндивидуальные подходы к рисованию, Один подход описан выше, а второй подход показывает, как использовать BufferedImage. Пример, используемый для обоих подходов, позволяет добавить несколько прямоугольников к кадру.

0

просто удалите каждый & quot; mousePosition.setText (...) & quot; в слушателях мыши они приведут к ненужным вызовам repaint ().

Затем добавьте два поля: & quot; int rx, ry; & quot ;, добавьте / измените несколько методов, как показано ниже:

        public void mouseDragged(MouseEvent event) {
//      mousePosition.setText("Dragged at [" + (x = event.getX()) + ", "
//              + (y = event.getY()) + "]");
        // call repaint which calls paint
        x = event.getX();
        y = event.getY();

        compRectPos();
        repaint();
    }

    private void compRectPos()
    {
        rx = x1;
        ry = y1;

        w = x - x1;
        h = y - y1;

        if ( w < 0)
            rx += w;
        if (h < 0)
            ry += h;

        w = Math.abs(w);
        h = Math.abs(h);

    }

    public void paint(Graphics g) {
        super.paint(g); // clear the frame surface
        g.drawString("Start Rec Here", x1, y1);
        g.drawString("End Rec Here", x, y);

        g.drawRect(rx, ry, w, h);

        cords.setText("w = " + w + ", h = " + h);
    }

Единственная проблема, которую я обнаружил, заключается в том, что прямоугольник не появляется при первом рисовании.

6

после перечитывания вашего вопроса кажется, что вам было бы наплевать на наличие нескольких прямоугольников

Вот решение только с одним за раз (что близко к тому, что вы должны были начать):

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;

public class MouseTracker4July extends JFrame implements MouseListener, MouseMotionListener {

    private static final long serialVersionUID = 1L;
    private final JLabel mousePosition;
    int x1, x2, y1, y2;
    int x, y, w, h;
    private final JLabel recStart;
    private final JLabel recStop;
    private final JLabel cords; // set up GUI and register mouse event handlers
    boolean isNewRect = true;

    public MouseTracker4July() {
        super( "Rectangle Drawer" );

        this.mousePosition = new JLabel();
        this.mousePosition.setHorizontalAlignment( SwingConstants.CENTER );
        getContentPane().add( this.mousePosition, BorderLayout.CENTER );

        JLabel text1 = new JLabel();
        text1.setText( "At the center the mouse pointer's coordinates will be displayed." );
        getContentPane().add( text1, BorderLayout.SOUTH );

        this.recStart = new JLabel();
        getContentPane().add( this.recStart, BorderLayout.WEST );

        this.recStop = new JLabel();
        getContentPane().add( this.recStop, BorderLayout.EAST );

        this.cords = new JLabel();
        getContentPane().add( this.cords, BorderLayout.NORTH );

        addMouseListener( this ); // listens for own mouse and
        addMouseMotionListener( this ); // mouse-motion events

        setSize( 800, 600 );
        setVisible( true );

    }

// MouseListener event handlers // handle event when mouse released immediately after press 
    public void mouseClicked( final MouseEvent event ) {
        this.mousePosition.setText( "Clicked at [" + event.getX() + ", " + event.getY() + "]" );

        repaint();
    }

// handle event when mouse pressed 
    public void mousePressed( final MouseEvent event ) {

        this.mousePosition.setText( "Pressed at [" + ( this.x1 = event.getX() ) + ", " + ( this.y1 = event.getY() ) + "]" );

        this.recStart.setText( "Start:  [" + this.x1 + ", " + this.y1 + "]" );

        this.isNewRect = true;

        repaint();
    }

// handle event when mouse released after dragging 
    public void mouseReleased( final MouseEvent event ) {
        this.mousePosition.setText( "Released at [" + ( this.x2 = event.getX() ) + ", " + ( this.y2 = event.getY() ) + "]" );

        this.recStop.setText( "End:  [" + this.x2 + ", " + this.y2 + "]" );

        repaint();
    }

// handle event when mouse enters area 
    public void mouseEntered( final MouseEvent event ) {
        this.mousePosition.setText( "Mouse entered at [" + event.getX() + ", " + event.getY() + "]" );
        repaint();
    }

// handle event when mouse exits area 
    public void mouseExited( final MouseEvent event ) {
        this.mousePosition.setText( "Mouse outside window" );
        repaint();
    }

// MouseMotionListener event handlers // handle event when user drags mouse with button pressed 
    public void mouseDragged( final MouseEvent event ) {
        this.mousePosition.setText( "Dragged at [" + ( this.x2 = event.getX() ) + ", " + ( this.y2 = event.getY() ) + "]" ); // call repaint which calls paint repaint();

        this.isNewRect = false;

        repaint();
    }

// handle event when user moves mouse 
    public void mouseMoved( final MouseEvent event ) {
        this.mousePosition.setText( "Moved at [" + event.getX() + ", " + event.getY() + "]" );
        repaint();
    }

    @Override
    public void paint( final Graphics g ) {
        super.paint( g ); // clear the frame surface 
        g.drawString( "Start Rec Here", this.x1, this.y1 );
        g.drawString( "End Rec Here", this.x2, this.y2 );

        int width = this.x1 - this.x2;
        int height = this.y1 - this.y2;

        this.w = Math.abs( width );
        this.h = Math.abs( height );
        this.x = width < 0 ? this.x1
            : this.x2;
        this.y = height < 0 ? this.y1
            : this.y2;

        if ( !this.isNewRect ) {
            g.drawRect( this.x, this.y, this.w, this.h );
        }

        this.cords.setText( "w = " + this.w + ", h = " + this.h );

    }

    public static void main( final String args[] ) {
        MouseTracker4July application = new MouseTracker4July();
        application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    }

} // end class MouseTracker
Каждый раз, когда я перетаскиваю мышь, возникает много мерцания, что вызвано переопределением метода paint () фрейма, как я предлагал ранее.
Это именно то, что мне было нужно, я знал, что я был близок, я просто не мог понять, как закончить эту вещь. Math.abs - это круто, потому что он сохраняет мою ширину и рост позитивными. Благодаря тонну. Еще один вопрос, это все «это». хорошая форма или личные предпочтения? Мне просто любопытно, потому что, поскольку я использую только один JFrame, он не является избыточным? Еще раз спасибо. Tyler
Лично я бы сказал, что «это» использование это немного предпочтений - есть другие, которые воинственно не согласны. Рад помочь.

Похожие вопросы