Select and drag Swing component

Asked

Viewed 1,069 times

1

I made an application that draws rectangles, dots, straights, etc. I wanted when the user clicked with the mouse on top of a drawn polygon, selected the polygon and dragged to where he wants on the screen, How to achieve this goal?

  • 1

    I don’t know much about Swing, and it’s been a while since I’ve worked with Java. But I believe that neither Swing nor Javafx have this kind of functionality, you would have to look for an existing library for this or a handler (and doing this at hand would be a good job).

  • I wanted to do it by hand, to train myself more in the use of language, but if I can’t, I’ll follow your tip :D

4 answers

1

I don’t know exactly how you’re creating polygons.

But if it is a java.awt.Component, I think that solves it:

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

public class Mover extends MouseAdapter {

  private Dimension snapSize = new Dimension( 1, 1 );
  private Component source;
  private Point pressed;
  private boolean potentialDrag;
  private static Mover instance;
  private Point locationBeforeMove;

  private Mover() {
  }

  public void deregisterComponent( Component... components ) {
    for ( Component component : components ) {
      component.removeMouseListener( this );
    }
  }

  public void registerComponent( Component... components ) {
    for ( Component component : components ) {
      component.addMouseListener( this );
    }
  }

  public Dimension getSnapSize() {
    return snapSize;
  }

  public void setSnapSize( Dimension snapSize ) {
    if ( snapSize.width < 1
        || snapSize.height < 1 ) {
      throw new IllegalArgumentException( "snapSize deve ser maior que 0" );
    }

    this.snapSize = snapSize;
  }

  @Override
  public void mousePressed( MouseEvent e ) {
    if ( !SwingUtilities.isLeftMouseButton( e ) ) {
      return;
    }
    if ( e.isConsumed() ) {
      return;
    }

    setupForDragging( e );
  }

  private void setupForDragging( MouseEvent e ) {
    source = e.getComponent();
    source.addMouseMotionListener( this );
    potentialDrag = true;

    pressed = e.getLocationOnScreen();

    locationBeforeMove = source.getLocation();
  }

  /**
   * Move the component to its new location. The dragged Point must be in the destination coordinates.
   */
  @Override
  public void mouseDragged( MouseEvent e ) {
    if ( !SwingUtilities.isLeftMouseButton( e ) ) {
      return;
    }
    if ( e.isConsumed() ) {
      return;
    }
    Point dragged = e.getLocationOnScreen();
    int dragX = getDragDistance( dragged.x, pressed.x, snapSize.width );
    int dragY = getDragDistance( dragged.y, pressed.y, snapSize.height );

    Component source = e.getComponent();

    Point location = locationBeforeMove;
    if ( location == null ) {
      return;
    }

    int locationX = location.x + dragX;
    int locationY = location.y + dragY;

    while ( locationX < 0 ) {
      locationX += snapSize.width;
    }

    while ( locationY < 0 ) {
      locationY += snapSize.height;
    }

    Dimension d = getBoundingSize( source );

    while ( locationX + source.getSize().width > d.width ) {
      locationX -= snapSize.width;
    }

    while ( locationY + source.getSize().height > d.height ) {
      locationY -= snapSize.height;
    }

    source.setLocation( locationX, locationY );
  }


  private int getDragDistance( int larger, int smaller, int snapSize ) {
    int halfway = snapSize / 2;
    int drag = larger - smaller;
    drag += (drag < 0) ? -halfway : halfway;
    drag = (drag / snapSize) * snapSize;

    return drag;
  }

  private Dimension getBoundingSize( Component source ) {
    if ( source instanceof Window ) {
      GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
      Rectangle bounds = env.getMaximumWindowBounds();
      return new Dimension( bounds.width, bounds.height );
    }
    else {
      return source.getParent().getSize();
    }
  }

  @Override
  public void mouseReleased( MouseEvent e ) {
    if ( !SwingUtilities.isLeftMouseButton( e ) ) {
      return;
    }
    if ( !potentialDrag ) {
      return;
    }

    source.removeMouseMotionListener( this );
    potentialDrag = false;
  }

  public static Mover getInstance() {
    if ( instance == null ) {
      instance = new Mover();
    }
    return instance;
  }
}

To use the class:

Poligono poligono = new Poligono();
Mover.getInstance().registerComponent( poligono );

0

First I think you have to review the use of Swing because and will not be continued, I suggest the use of Java FX that is very cool, easy to use and has very cool components.

About the problem you would have to use some resource of drag & drop, that will work with the image positions. Something like this.

  • I will give a survey on how java FX works, thanks for the tip!

0

Depending on the purpose of this, you would have to do "on the arm": Detecting where the guy clicked, identifying which polygon is, and repainting the polygon on the screen by moving it and so on... That depends on how you’re drawing the polygon

  • I’m drawing with the primitives of the Java Graphical API, the difficulty is identify if the guy clicked on the polygon, give me a hint of how to do this...

  • in college I had to make a problem like this and the solution found was to identify which point closer to the clicked location. From this way of which polygon belonged to that point and selected.

  • Um, I’ll try to use that idea here :D

0


If you want to do it by hand... it’s been a while since I work with Java, but I’ll try to give you some tips.

Whenever the user draws a polygon, keep in memory the coordinates of this polygon. It is good to keep also a kind of "Z-index" so you can have polygons on each other (if you want to allow this)

private Vector<Poligono> poligonos;
public Vector<Poligono> getPoligonos() { return this.poligonos; }
public void setPoligonos(Vector<Poligono> poligonos) { this.poligonos = poligonos; }

public void desenharPoligono(int startX, int startY, int endX, int endY) {
    this.getPoligonos().push(new Poligono(startX, startY, endX, endY));
}

When the user clicks fast (do not click and drag), scan your polygon list to see if it clicked on a coordinate that belongs to a polygon... If yes, bang, select your polygon!

public void verificarCoordenadas(int x, int y) {
    for (Poligono poligono : this.getPoligonos()) {
        if (poligono.contemCoordenada(x, y)) {
            poligono.selecionar();
            return;
        }
    }
}

If I give you more tips I take your learning challenge alone. Your next steps would be to create the class Poligono and implement their methods (contemCoordenada, selecionar, mover related)...

Gave me a little bit of Java now.

  • hum very good, is already a great start for me, thanks for the tip :D

Browser other questions tagged

You are not signed in. Login or sign up in order to post.