Swing Objekte bewegen mit MouseMotionListener

da_roman

Mitglied
Hallo!

Ich hätte eine Frage bzgl. der Methode mouseMoved.
Ich möchte gerne Objekte in einen JPanel mittels Drag and Drop bewegen.
Dazu verwende ich einen MouseMotionListener, der Aufruf erfolgt in der Methode MouseMoved().
Also, die Objekte werden nicht mit mouseDragged() bewegt, sondern durch einfaches Bewegen der Maus.

Die Objekte sollen sich mit der Maus mitbewegen, die Maus kann sich also auch an einen anderen
Ort als die Objekte befinden. Daher berechne ich mir die Differenz zwischen Maus-Koordinaten und Objekten, und setze dann die Werte neu. Meine Implementierung:
Java:
/**
 * @param x coordinate of the mouse
 * @param y coordinate of the mouse
 */
public void move(int x, int y) {
  float diffX, diffY;
  Iterator<Vertex> it = vertices_.iterator();
  while(it.hasNext()) {
    Vertex v = it.next();
    diffX = v.getX()-x;
    diffY = v.getY()-y;
    v.setX(x-diffX);
    v.setY(y-diffY);
      
    // debug out:
    System.out.println("Vertex:"+v.getX()+" "+v.getY());
    System.out.println("Mouse: "+x+" "+y);
    System.out.println("diffX:"+diffX+", diffY:"+diffY);
    System.out.println("--------------------------------");
  }
}

Das funktioniert leider nicht so ganz. Die Objekte springen immer zwischen Maus hin und her
Ein Blick auf die Ausgabe verrät auch was da schief läuft:

Vertex:357.0 451.0
Mouse: 305 312
diffX:-52.0, diffY:-139.0
--------------------------------
Vertex:253.0 171.0
Mouse: 305 311
diffX:52.0, diffY:140.0
--------------------------------
Vertex:357.0 449.0
Mouse: 305 310
diffX:-52.0, diffY:-139.0
--------------------------------
Vertex:253.0 169.0
Mouse: 305 309
diffX:52.0, diffY:140.0
--------------------------------
Vertex:357.0 447.0
Mouse: 305 308
diffX:-52.0, diffY:-139.0
--------------------------------

usw...
Anscheinend wird die Differenz durch zweifachen Aufruf doppelt abgezogen, daher springen die Objekte immer hin und her :/.

Hat jemand eine Idee was ich anders machen könnte?
danke & lg
 
Meinst du vielleicht so?

Java:
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;

public class Vertex extends JLabel {
	public Vertex() {
		this((String)null);
	}
	public Vertex(String s) {
		super(s);
		
		MouseAdapter adapter = new MouseAdapter() {
			private Point mouseEnteredLoc;
			
			public void mouseEntered(MouseEvent e) {
				mouseEnteredLoc = new Point(e.getX(), e.getY());
			}
			public void mouseMoved(MouseEvent e) {
				setLocation(calcNewCoordinate(getX(), e.getX(), mouseEnteredLoc.x),
						calcNewCoordinate(getY(), e.getY(), mouseEnteredLoc.y));
			}
			private int calcNewCoordinate(int vectorPx, int mousePx, int enteredPx) {
				return(vectorPx + mousePx - enteredPx);
			}
		};
		addMouseListener(adapter);
		addMouseMotionListener(adapter);
	}
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				buildGui();				
			}
		});
	}
	private static void buildGui() {
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		JLayeredPane content = new JLayeredPane();
		
		Vertex vertexA = new Vertex("Test A");
		vertexA.setSize(vertexA.getPreferredSize());
		content.add(vertexA, Integer.valueOf(0));
		
		Vertex vertexB = new Vertex("Test B");
		vertexB.setSize(vertexB.getPreferredSize());
		content.add(vertexB, Integer.valueOf(1));
		
		frame.setContentPane(content);
		frame.setSize(500, 500);
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
	}
}
 
Zunächst mal danke für die Antwort 🙂,
hmmmmm nicht wirklich, was ich machen möchte ist sowas:
(sry, etwas mehr code als erwartet..)

Main(MotionDemo.java)
Java:
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class MotionDemo {
	public static void main(String[] args) {    
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				Canvas c = new Canvas();
				JFrame f = new JFrame("MotionDemo");
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.add(c);
				f.pack();
				f.setLocationRelativeTo(null);
				f.setVisible(true);
			}
		});
	}
}


Zeichenfläche(Canvas.java)
Java:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.Iterator;
import java.util.LinkedList;

import javax.swing.JPanel;

public class Canvas extends JPanel implements MouseMotionListener{

	private static final long serialVersionUID = 1L;
	LinkedList<Vertex> vertices;
	
	public Canvas() {
		vertices = new LinkedList<Vertex>();
		vertices.add(new Vertex(20,40));
		vertices.add(new Vertex(40,20));
		vertices.add(new Vertex(40,60));
		vertices.add(new Vertex(60,40));
		addMouseMotionListener(this);
		setBackground(Color.white);
		setPreferredSize(new Dimension(500,500));
	}
	
  	public void move(int x, int y) {
  		int diffX, diffY;
  		Iterator<Vertex> it = vertices.iterator();
  		while(it.hasNext()) {
  			Vertex v = it.next();
  			diffX = v.getX()-x;
  			diffY = v.getY()-y;
  			v.updateCoordinates(x-diffX, y-diffY);
    	}
	}

	@Override
	public void mouseDragged(MouseEvent arg0) {
	}
	
	@Override
	public void mouseMoved(MouseEvent e) {
		move(e.getX(), e.getY());
		repaint();
	}
	
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setXORMode(getBackground());
		Graphics2D g2d = (Graphics2D)g;
		
		Iterator<Vertex> it = vertices.iterator();
		while(it.hasNext()) {
			it.next().draw(g2d);
		}
	}
}

das zu bewegende Objekt(Vertex.java)
Java:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;

import javax.swing.JLabel;
 
public class Vertex extends JLabel {

	private static final long serialVersionUID = 1L;
	private static final int WIDTH = 6;
	private Ellipse2D ellipse;
	int x;
    int y;
    
    public Vertex(int x, int y) {
    	this.ellipse = new Ellipse2D.Float(x-(WIDTH/2), y-(WIDTH/2), WIDTH, WIDTH);
    	this.x = x;
    	this.y = y;
    }
    public void updateCoordinates(int x, int y) {
    	setX(x);
    	setY(y);
    	this.ellipse.setFrame(x-(WIDTH/2), y-(WIDTH/2), WIDTH, WIDTH);
    }
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	public void draw(Graphics2D g) {
		g.setColor(Color.black);
		g.draw(ellipse);
	}
}

Führt man das Programm aus, und bewegt die maus im JPanel sieht man das "hin und her hüpfen" der Objekte. Also der eigentliche Unterschied zwischen unseren 2 Programmen ist dass ich mehrere Objekte ausgehend von einen Punkt aus bewegen möchte, also ein bisschen anders als "drag and drop"
danke und lg
 
Meinst du so in etwa?
Wollte schon mit dir schimpfen, da ich dachte du vermischt AWT und Swing, und dann war Canvas doch kein Canvas. ;(

Java:
package org.javaforum.daroman;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class MotionDemo {
    private static VertexController vertexController;
	
	public static void main(String[] args) {    
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
            	vertexController = new VertexController();
            	
                final JFrame f = new JFrame("MotionDemo");
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.add(new JPanel() {
                	protected void paintComponent(Graphics g) {
                		super.paintComponent(g);
                		vertexController.paintVertexes((Graphics2D) g);
                	}
                });
                f.getContentPane().addMouseMotionListener(new MouseAdapter() {
                	public void mouseMoved(MouseEvent e) {
                		vertexController.mouseLocationChanged(e.getX(), e.getY());
                		f.repaint();
                	}
                	public void mouseDragged(MouseEvent e) {
                		mouseMoved(e);
                	}
				});
                f.setSize(500, 500);
                f.setLocationRelativeTo(null);
                f.setVisible(true);
            }
        });
    }
}
Java:
package org.javaforum.daroman;

import java.awt.Graphics2D;
import java.awt.Point;
import java.util.LinkedList;

public class VertexController {
	private static final Point[] VERTEX_MODS = {
		new Point(1, 0),
		new Point(0, 1),
		new Point(-1, 0),
		new Point(0, -1),
	};
	
	private static final int VERTEX_CUROR_DISTANCE = 20;
	
	private LinkedList<Vertex> vertices;
	
	public VertexController() {
        vertices = new LinkedList<Vertex>();
        
        vertices.add(new Vertex(20, 40));
        vertices.add(new Vertex(40, 20));
        vertices.add(new Vertex(40, 60));
        vertices.add(new Vertex(60, 40));
	}
	public void paintVertexes(Graphics2D g) {
		for(Vertex vertex:vertices) {
			vertex.paint(g);
		}
	}
	public void mouseLocationChanged(int x, int y) {
		if(vertices.size() < VERTEX_MODS.length) {
			throw new IllegalStateException("Less vertexes as need");
		}
		
		for(int i = 0, size = VERTEX_MODS.length; i < size; i++) {
			Point mod = VERTEX_MODS[i];
			Vertex vertex = vertices.get(i);
			mouseLocationChanged(x, y, vertex, mod);
		}
	}
	public void mouseLocationChanged(int x, int y, Vertex vertex, Point mod) {
		int hDist = mod.x * VERTEX_CUROR_DISTANCE;
		int vDist = mod.y * VERTEX_CUROR_DISTANCE;
		
		vertex.setLocation(x - vertex.getWidth() - hDist, y - vertex.getHeight() - vDist);
	}
}
Java:
package org.javaforum.daroman;

import java.awt.Color;
import java.awt.Graphics2D;
 
public class Vertex {
    private static final int DEFAULT_WIDTH = 6;
    
    private int x;
    private int y;
    
    private int width;
    private int height;
    
    public Vertex(int x, int y) {
        this.x = x;
        this.y = y;
        
        width = DEFAULT_WIDTH;
        height = DEFAULT_WIDTH;
    }

    public void paint(Graphics2D g) {
        g.setColor(Color.black);
        g.drawOval(x, y, width, height);
    }
    
    
    public int getX() {
        return x;
    }
    public void setX(int x) {
        this.x = x;
    }
    public int getY() {
        return y;
    }
    public void setY(int y) {
        this.y = y;
    }
    public void setWidth(int width) {
		this.width = width;
	}
    public int getWidth() {
		return width;
	}
    public void setHeight(int height) {
		this.height = height;
	}
    public void setLocation(int x, int y) {
    	setX(x);
    	setY(y);
	}
    
    public int getHeight() {
		return height;
	}
}
 

Neue Themen


Zurück
Oben