JPanel nicht fließend verschiebbar

BlubBlub

Bekanntes Mitglied
Hi ich habe den unten aufgelisteten Code geschrieben.
In einem JFrame ist ein JPanel eingebettet. Dieses JPanel namens statePanel soll verschiebbar sein.
Der Benutzer drückt dabei mit der Maus auf das JPanel und kann es durch eine "Drag" Bewegung verschieben.

Problem: Das Panel folgt nicht exakt dem Mauszeiger. Sobald ich den Mauszeiger bewege, hinkt das JPanel enorm hinterher und ist recht sprunghaft. Vorallem liegt das JPanel auch nicht direkt unter dem Mauszeiger.
Was muss ich ich korrigieren, damit das JPanel immer direkt an der Postion ist wo der Mauszeiger sich befindet, sobald der Benutzer die Maustaste über dem JPanel gedrückt hält und die Maus bewegt?

Java:
public class Starter
{
	public static void main(String[] args)
	{
		new GraphicAnimator();
	}
}

Java:
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;

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


public class GraphicAnimator extends JFrame
{
	private Container contentPane;
	private StatePanel statePanel;
	
	public GraphicAnimator()
	{
		super();
		setSize(700, 500);
		setLayout(new FlowLayout());
		contentPane = getContentPane();
		statePanel = new StatePanel();
		contentPane.add(statePanel);
		
		setVisible(true);
	}
}

Java:
import java.awt.Color;
import java.awt.Dimension;

import javax.swing.JPanel;
import javax.swing.border.LineBorder;


public class StatePanel extends JPanel
{	
	public StatePanel()
	{
		setPreferredSize(new Dimension(200, 100));
		setBackground(Color.CYAN);
		setBorder(new LineBorder(Color.BLACK));
		this.addMouseMotionListener(new StatePanelMouseMotionListener(this));
	}
}

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


public class StatePanelMouseMotionListener implements MouseMotionListener
{
	private StatePanel statePanel;
	
	public StatePanelMouseMotionListener(StatePanel statePanel)
	{
		this.statePanel = statePanel;
	}

	@Override
	public void mouseDragged(MouseEvent me) 
	{
		statePanel.setLocation(me.getX(), me.getY());	
	}

	@Override
	public void mouseMoved(MouseEvent me) {}
}
 
Sind die Koordinaten des MouseEvents nicht relativ zu der Komponente auf der er liegt?
Ich meine es selbst mal bei mir gemacht zu haben und da hatte ich nicht direkt die Koordinaten des MEs genommen, sondern diese auf die Koordinaten des Fensters addiert.
 
Jau du hast recht. Danke für den Hinweis. Ich habe den Code des MouseMotionListeners jetzt geändert. Der JPanel folgt jetzt dem Mauszeiger beim Drag.

Folgendes stört mich allerdings noch:
Angenommen der Mauszeiger ist in der Mitte des Panels.
Dann bewege ich bei gedrückter Maustaste die Maus.
Das Panel folgt der Maus.
Die Maus befindet sich beim Bewegen des Panels aber nicht mehr in ihrer Ursprünglichen
Position innerhalb des Panels.
Das heißt die Maus ist nicht mehr in der Mitte des Panels, sondern die ganze Zeit über
an der oberen linken Ecke des Panels.

Frage: Wie schafe ich es, dass die Maus weiterhin an der Stelle im JPanel ist, wo ich die Drag
Aktion gestartet habe.

Anmerkung: Im Code gibts die Variablen "mauszeigerXinPanel" und "mauszeigerYinPanel".
Damit kann ich festlegen, dass sich der Mauszeiger nicht in der oberen linken Ecke des Panels
befindet sondern um die jeweilige Pixel Anzahl verschoben im JPanel. Ich kriege es aber nicht
hin, dass der Mauszeiger an der Ursprünglichen Position bleibt.


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


public class StatePanelMouseMotionListener implements MouseMotionListener
{
	@Override
	public void mouseDragged(MouseEvent me) 
	{
		System.out.println("\n Mauskoordinaten relativ zur Mausposition im Panel: " + me.getX() + " und " +  me.getY());
		System.out.println("\n JPanelkoordinaten relativ zum JFrame:" + me.getComponent().getX() + " und " + me.getComponent().getY());
		
		int mauszeigerXinPanel = -30;
		int mauszeigerYinPanel = -50;
		
		int X = me.getX()+me.getComponent().getX()+mauszeigerXinPanel;
		int Y = me.getY()+me.getComponent().getY()+mauszeigerYinPanel;
		
		me.getComponent().setLocation(X, Y);	
	}	
	
	@Override
	public void mouseMoved(MouseEvent me) {}
}
 
Ja das Problem hatte ich so gelöst:

Meine Komponente, die ich ziehen will ist MouseMotionListener und MouseListener
Java:
        // Exemplarvaribablen
        private boolean _isDragStarted = false;
	private Point _startPosDifference;


        // Methoden
	public void mouseDragged(MouseEvent e)
	{
		// Hier habe ich eigentlich noch eine Abfrage, so dass man nur auf einen kleinen 
                // Bereich klicken kann, um zu ziehen
		// Sobald der drag beginnt wird zuerst der Startpunkt gesetzt und der Status für den Drag
                // auf TRUE gesetzt. Danach wird genau das gemacht, was du auch schon hast.
			if (!_isDragStarted)
			{
				_startPosDifference = new Point(
						this.getLocation().x - e.getLocationOnScreen().x,
						this.getLocation().y -  e.getLocationOnScreen().y);
				_isDragStarted = true;
			}
			else
			{
				setLocation(e.getLocationOnScreen().x + _startPosDifference.x , 
						e.getLocationOnScreen().y + _startPosDifference.y);
			}
		
	}

        // Natürlich muss man den Drag wieder reseten, sonst kriegt man keinen neuen Startpunkt
	public void mouseReleased(MouseEvent arg0)
	{
                _isDragStarted = false;
         }
 
Zuletzt bearbeitet:
So hab das jetzt auch angepasst. Funktioniert bei mir jetzt auch wunderbar, also Danke erstmal dafür.
Nun habe ich zwei Panels erstellt. Beide kann ich nun mit der Maus verschieben.
Ich habe in das JFrame die beiden Panels in folgender Reihenfolge platziert (siehe Pseudocoud).

Code:
frame.setLayout(new FlowLayout());
frame.getContentPane().add(PanelA);
frame.getContentPane().add(PanelB);

Wenn ich nun das PanelA über das PanelB ziehe, so verdeckt das PanelA das PanelB.
Wenn ich das PanelB über das PanelA ziehe, so liegt PanelB unter PanalA.
Dies liegt daran, dass ich in die contentPane des JFrame zuerst PanelA und dann PanelB eingefügt habe.

Frage: Wie schaffe ich es, dass ein Panel welches verschoben wird immer über dem Panel liegt das grad nicht
verschoben wird?
 
Nee Null-Layout Manager ist keine gute Idee, da man sich später um die Größenanpassung der Panels und deren Darstellung etc. auf verschiedenen Plattformen selbst kümmern muss.

Ich habe das Problem jetzt gelöst, indem ich die Panels auf dieselbe Ebene innerhalb der Layered Pane gesetzt habe und dabei die Methode moveToFront(Component) verwende.

Allerdings habe ich noch ein weiteres Problem:
Nachdem ich die Position der Panels durch verschieben verändert habe und das JFrame
vergrößer/verkleiner oder maximiere/minimiere sind die beiden
verschobenen Panels wieder in der ursprünglichen Position.
Ich glaub das liegt daran, dass bem vergrößern/verkleinern und maximieren/minimieren das JFrame und seine Inhalte neu gezeichent werden.

Frage: Wie schaffe ich es, dass die neuen Panel Positionen erhalten bleiben?
 
Zuletzt bearbeitet:
Nee Null-Layout Manager ist keine gute Idee, da man sich später um die Größenanpassung der Panels und deren Darstellung etc. auf verschiedenen Plattformen selbst kümmern muss.
...
Nachdem ich die Position der Panels durch verschieben verändert habe und das JFrame
vergrößer/verkleiner oder maximiere/minimiere sind die beiden
verschobenen Panels wieder in der ursprünglichen Position.
Das macht der LayoutManager...

Frage: Wie schaffe ich es, dass die neuen Panel Positionen erhalten bleiben?

Mit einem null-Layout. Entweder oder. Du musst wählen.
 
Nach längerem hin und her überlegen bin ich auch zum Entschluss gekommen das Null Layout zu
wählen, alles ändere wäre nur trickserei gewesen und unnötig kompliziert.

Anfangs wollte ich das Null Layout nicht verwendent, weil ich in den einzelnen verschiebbaren Panels
verschiedene Komponenten habe. Damit man die Komponenten sieht füge ich sie zuerst in das Panel
ein und anschließend setze ich die größe des Panel mit setBounds. Wobei um die ideale Größe zu erstellen frage ich das Panel nach dem Einfügen der einzelnen Komponenten nach seiner PreferredSize, welche ich anschließend in setBounds(...) setze. Somit ist es letztlich doch nicht so schlimm, dass ich für das LayeredPane keinen Layout Manager habe, der sonst die automatische Größenanpassung der Panels vorgenommen hätte.

Thx für die Tipps
 
Naja, "Trickserei" kann entweder ein Hack sein, oder irgendwas geschicktes 😉 Man könnte sich vermutlich eine Lösung überlegen, bei der man die Components am Anfang einmal mit einen LayoutManager platziert, aber dann tatsächlich das null-Layout verwendet, um sie noch veschieben zu können. Eine "Mischung" (also einige layoutete Components und einige verschiebbare) auf EINEM Container wäre aber wohl wirklich ziemlich frickelig.
 

Neue Themen


Zurück
Oben