Component verschieben, Ruckeln

Hallo
Ich möchte, dass ein Component per Maus herum gezogen werden kann:

		public void mouseMoved(MouseEvent me){
			if(zahnrad_dragged){
				draggedZahnrad.setPos(new Point(
me.getX()-draggedZahnrad.breite/2,me.getY()-draggedZahnrad.höhe/2));
				revalidate();
				draggedZahnrad.revalidate();
				repaint();
			}
		}```

zahnrad_dragged wird in mousePressed auf true und in mouseReleased auf false gesetzt
Die Methode setPos setzt die Bounds des Components.

Das Problem ist:
Es ruckelt ohne Ende, teilweise "teleportiert" sich der Component über einige hundert Pixel umher

Nur ein Lösungsvorschlag kann nicht versprechen das es funktioniert. Du machst sehr viele Anfragen bei MouseMove und er muss natürlich entsprechend oft neu zeichnen. Bau um das If einen Timer, wenn die Maus irgendwie 10 milisekunden nicht bewegt worden ist führt du das if aus.

Habe mal so etwas änliches gebaut in GWT (kannst du so nicht verwenden musst du umbauen natürlich

			scrollTimer = new Timer() {
				@Override
				public void run() {
					fitToContent();
				}
			};
		}
		scrollTimer.cancel();
		scrollTimer.schedule(UPDATE_DELAY);

Ich glaub das ist hier nicht angebracht

oder verschiebe keine Komponenten!,
was ist das für eine Komponente, nur einfache graphische Anzeige eines Bildes oder einer paintComponent-Zeichnung?

dann wäre es möglich, die gesamte Fläche unter Kontrolle eines JPanels zu stellen, mir Mauskoordinaten zu arbeiten,
berechnen was unter der Maus sein sollte, dieses Element passend verschieben, also neue Koordinaten,
und repaint() immer noch, malt die Komponente X an anderer Stelle,
dragged auch beteiligt

edit: nahezu kein Swing-Thema gehört in Java Basics, und das hier ist auch kein besonders einfaches, verschoben,
bei Gelegenheit ruhig darauf achten

ES handelt sich um eine Klasse, die aus JComponent erbt und eine Paintcomponent Methode besitzt in der das “Hintergrungbild” gezeichnet wird.

Malen in AWT und Swing hilft nicht?

Ja, natürlich kann man es so machen, dass man einfach ein Bild an eine Stelle im Mainpanel malt und die Position verändert.Aber ein bekannter von mir der auch Java programmiert sagte mir, dass es mit Components erstens weniger ruckelt(hat sich nicht bestätigt) und zweitens es eleganter ist.

totaler humbuck.

zeig mir bitte diesen bekannten xD

Und was genau macht das eine jetzt ruckliger ?

edit:Ich habs jetzt umgeschrieben und es ruckelt genauso,wenn ich nur das bild bewege.

Printe mal im Listener irgendwas zur Konsole. Dann siehste wie viele Aufrufe das sind zum neuzeichnen.

Meinst du sowas?

import java.awt.Container;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.SwingUtilities;

public class Container_MouseMover extends MouseAdapter {
    private Container compToListen;
    private Container compToMove;
    
    private Point oldEget = new Point();
    private boolean checkOutOfBounds;
    public Container_MouseMover(Container compToListen_g, Container compToMove_g, final boolean checkOutOfBounds_g) {
        checkOutOfBounds = checkOutOfBounds_g;
        this.compToListen = compToListen_g;
        this.compToMove = compToMove_g;
        this.compToListen.addMouseMotionListener(this);
        this.compToListen.addMouseListener(this);
    }

    @Override public void mouseDragged(MouseEvent e) {
        if (SwingUtilities.isLeftMouseButton(e)) {
            double xOnScreen_scaled = e.getXOnScreen();
            double yOnScreen_scaled = e.getYOnScreen();

            int newX = (int) (compToMove.getX()+xOnScreen_scaled-oldEget.x);
            int newY = (int) (compToMove.getY()+yOnScreen_scaled-oldEget.y);
            oldEget.setLocation(xOnScreen_scaled, yOnScreen_scaled);

            if (checkOutOfBounds) {
                if (newX > compToMove.getParent().getWidth()-10) {
                    newX = compToMove.getParent().getWidth()-10;
                }
                if (newX < 0-compToMove.getWidth()+10) {
                    newX = 0-compToMove.getWidth()+10;
                }
                if (newY > compToMove.getParent().getHeight()-10) {
                    newY = compToMove.getParent().getHeight()-10;
                }
                if (newY < 0-compToMove.getHeight()+10) {
                    newY = 0-compToMove.getHeight()+10;
                }
            }
            compToMove.setLocation(newX, newY);
        }
    }
    @Override public void mousePressed(MouseEvent e) {
        if (SwingUtilities.isLeftMouseButton(e))
            oldEget.setLocation(e.getXOnScreen(), e.getYOnScreen());
    }

    public void removeListener() {
        compToListen.removeMouseMotionListener(this);
        compToListen.removeMouseListener(this);
    }
}```

Guck dir einfach mal das Beispiel an: DragLayout

2x revalidate und 1x repaint ist ausserdem total unnötig. Revalidate brauchst du nur, wenn das Layout neu berechnet werden muss.

hoffentlich wird nicht das Bild erst noch jedes Mal neu geladen? (bzw. hoffentlich schon bisher, dann wäre noch Potential zur Verbesserung)
etwas Beispielcode einer ruckligen Variante wäre nach so vielen Postings ganz nett

Auch wenn der bisher gepostete Code nicht mal annhähernd reicht, um das Problem zu erkennen oder zu beheben, deutet die Symptomatik darauf hin, dass der MouseListener, der die Component verschieben soll, an der Component selbst hängt. Das würde das ruckeln und springen erklären: In dem Moment, wo die Component verschoben wird, ist die Maus (bezogen auf die Component) schlagartig ganz woanders.
Mehr Code wäre in jedem Fall hilfreich, aber Components draggen ist schon ein bißchen Tricky. Eine GlassPane könnte helfen…

Also wenn ich mal meinen Senf dazugeben darf…

Das hier… was ziemlich dreckig unordentlich schlecht und… naja so ist wie man es nicht machen sollte…

import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

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


public class Draggable {
	
	public Draggable(){
		final JFrame f = new JFrame();
		f.setSize(800, 600);
		f.setLocationRelativeTo(null);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		JPanel content = new JPanel();
		content.setLayout(null);
		final JPanel p = new JPanel();
		p.setBounds(10, 10, 100, 100);
		content.addMouseMotionListener(new MouseMotionListener() {
			public void mouseMoved(MouseEvent arg0){}
			public void mouseDragged(MouseEvent arg0){
				if(p.getBounds().contains(arg0.getPoint()))
				p.setLocation(arg0.getX() - 50, arg0.getY() - 50);
			}
		});
		p.setBackground(Color.GREEN);
		content.add(p);
		f.add(content);
		f.setVisible(true);
	}
	
	public static void main(String[] args) {
		new Draggable();
	}
}

ruckelt bei mir gar nicht.

naja, es gibt am Anfang schon evtl. einen ganz schönen Sprung,
egal wo man klickt, das grüne Panel ist danach zentriert unter dem Mauszeiger, (zentriert wegen fester Konstanten 50 zu 100)

um den Standardcode zu ergänzen, kommt dem von IDC wahrscheinlich nahe:

public class Test2
{
    static int x;
    static int y;

    public static void main(String[] args)
    {
        final JFrame f = new JFrame();
        f.setSize(800, 400);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel content = new JPanel();
        content.setLayout(null);
        final JPanel p = new JPanel();
        p.setBounds(10, 10, 100, 100);
        content.addMouseMotionListener(new MouseMotionAdapter()
            {
                public void mouseDragged(MouseEvent arg0)
                {
                    p.setLocation(arg0.getX() - x, arg0.getY() - y);
                }
            });
        content.addMouseListener(new MouseAdapter()
            {
                public void mousePressed(MouseEvent e)
                {
                    x = e.getX()-p.getLocation().x;
                    y = e.getY()-p.getLocation().y;
                }
            });
        p.setBackground(Color.GREEN);
        content.add(p);
        f.add(content);
        f.setVisible(true);
    }
}

damit sollte die Bewegung hinsichtlich Positionen narrensicher sein, maximal noch Probleme beim Zeichnen möglich, wie ich es ursprünglich verstanden hatte,

ein Test auf Klick im Bereich des Panels mit evtl. Ablehnung der Bewegung habe ich hier nicht aufgenommen

war eben bezogen auf

dazu kann man doch „gibt am Anfang schon evtl. einen ganz schönen Sprung“ schreiben

schade dass du nochmal was dazuschreiben musst und dann ich usw. :wink:

Klasse des Components, der verschoben werden soll (grob):

public class Comp extends JComponent{

	private static final long serialVersionUID = 1L;
	int breite;
	int höhe;
	BufferedImage bild;
	
	public Comp(BufferedImage bild, Point pos){
		this.breite = bild.getWidth();
		this.höhe = bild.getHeight();
		this.bild = bild;
		this.setBounds(pos.x, pos.y, breite, höhe);
		repaint();
	}
	
	@Override
	protected void paintComponent(Graphics g){
		super.paintComponent(g);
		g.drawImage(bild, 0, 0, this);
	}
	
	public void setPos(Point pos){
		this.setBounds(pos.x, pos.y, breite, höhe);
	}

	public Rectangle getRect(){
		return this.getBounds();
	}

Haupt-Panel an dem auch der Maus-Listener hängt:

@Override
public void mousePressed(MouseEvent arg0) {
	dragged = true;
	Rectangle cursor = new Rectangle(arg0.getX(), arg0.getY(), 1, 1);
	if(cursor.intersects(comp.getRect())){//comp ist Instanz der Klasse Comp ist dem Panel schon hinzugefügt
		draggedComp = comp;
	}
}

@Override
public void mouseReleased(MouseEvent arg0) {
	dragged = false;
	draggedComp = null;
}

@Override
public void mouseDragged(MouseEvent me){
		mouseMoved(me);
}
@Override
public void mouseMoved(MouseEvent me){
	if(dragged){
		draggedComp.setPos(new Point(
				me.getX()-draggedComp.breite/2,me.getY()-draggedComp.höhe/2));
				revalidate();
			}
		}

poste bitte ein kskb.