keine weiteren Events während Drag&Drop Operation möglich?

carbone

Mitglied
Hallo,
meine Umgebung ist folgende:
Windows XP Pro SP3
JRE 1.6.0_21

CrossPosting Hinweis: ich habe das ganze auch bei tutorials.de gespostet

Und ich habe folgendes Problem (egal ob AWT oder SWING):

ich habe ein DnD von Datein außerhalb meiner Anwendung (z.B. %DESKTOP%\datei.txt) auf das Hauptfenster meiner Anwendung realisiert. Das funktioniert alles optimal.
Nun möchte ich aber das das ganze auch visulalisiert wird, sprich ich möchte mein Fenster animieren, wenn ein dragEnter() bzw. ein dragExit() stattfindet. Z.B. soll das Fenster bei einem dragEnter() verbreitert und bei einem dragExit() wieder verkleinert werden. Das scheint aber nicht sauber zu funktionieren. Die Animation beim dragEnter() funktioniert sauber. Beim dragExit() jedoch wird zwar das Fenster verkleinert, jedoch scheint das nicht bis "Windows" durchzudringen, da eine Art Schatten bzw. Ghost des Fensters immernoch zu sehen ist.
Wenn ich die Animation (ohne DnD) nur über mouseEnter() bzw. mouseExited() realisiere funktioniert es wunderbar. Alles wird korrekt gezeichnet. Nun dachte ich mir ich feuere einfach ein MouseEvent bei dragEnter() und dragExit() ab. Naja so leicht ist es nun auch wieder nicht.

Es scheint also an der noch stattfindenden DnD Operation zu liegen, die bestimmte Events blockiert.
Ja ich weiß... EventQueue etc. Aber ich kann genau 1 MouseEvent dispatchen während eines DnD. Egal ob MouseEvent.MOUSE_PRESSED oder MouseEvent.MOUSE_EXITED etc., es wird immer nur ein MouseEvent.MOUSE_ENTERED dispatched.


Ich habe nirgends etwas darüber gefunden wie DnD genau abläuft, und warum bestimmte Events zum Teil blockiert werden.
Ich denke mal ein DnD auf ein DropTarget ist ein MouseEvent. Wenn der DnD also in ein DropTarget "entered" und solange der Drop nicht abgeschlossen ist ist es nur ein MouseEvent.MOUSE_ENTERED. Und den kann man auch nur genau einmal per Hand weiter-dispatchen!?

Wie kann ich die Animation sauber realisieren. Habt ihr Ideen?
Ein händisches repaint aller Komponenten habe ich auch schon probiert. Evtl. aber an der falschen Stelle!?

Nier das Fenster:
Java:
public class FrameController implements MouseListener, DropTargetListener {

	private static FrameController self;

	public static synchronized FrameController getInstance() {
		if (self == null) {
			FrameController.self = new FrameController();
			return FrameController.self;
		}
		return FrameController.self;
	}

	private Frame frame;
	private boolean isDragAndDropEvent;

	public void show() {
		frame = new Frame();
		frame.setUndecorated(true);
		frame.setBounds((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth()/2-50),0,100,40);
		frame.addMouseListener(this);
		frame.add(new Label("TEST"));
		frame.setDropTarget(new DropTarget(frame, this));
		frame.setVisible(true);
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		//Point mousePointer = frame.getMousePosition(true);
		//frame.dispatchEvent(new MouseEvent(frame, MouseEvent.MOUSE_EXITED, GregorianCalendar.getInstance().getTimeInMillis(), MouseEvent.BUTTON1_DOWN_MASK, mousePointer.x, mousePointer.y, MouseEvent.BUTTON1, false));
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		Animator.setAnimation(Animator.ANIMATE_WIDTH_ENLARGE, frame, 40);
		Animator.start(1, 100);
	}

	@Override
	public void mouseExited(MouseEvent e) {
		Animator.setAnimation(Animator.ANIMATE_WIDTH_SHRINK, frame, 40);
		Animator.start(1, 100);
	}

	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		
	}

	@Override
	public void dragEnter(DropTargetDragEvent dtde) {
		this.isDragAndDropEvent = true;
		Point mousePointer = frame.getMousePosition(true);
		//docklet.dispatchEvent(new MouseEvent(frame, MouseEvent.MOUSE_DRAGGED, GregorianCalendar.getInstance().getTimeInMillis(), MouseEvent.BUTTON1_DOWN_MASK, mousePointer.x, mousePointer.y, MouseEvent.BUTTON1, false));
		this.mouseEntered(new MouseEvent(frame, MouseEvent.MOUSE_ENTERED, GregorianCalendar.getInstance().getTimeInMillis(), MouseEvent.BUTTON1_DOWN_MASK, mousePointer.x, mousePointer.y, MouseEvent.BUTTON1, false));
	
	}

	@Override
	public void dragExit(DropTargetEvent dte) {
		//dte.getDropTargetContext().dropComplete (true);
		//Point mousePointer = frame.getMousePosition(true);
		//docklet.dispatchEvent(new MouseEvent(frame, MouseEvent.MOUSE_EXITED, GregorianCalendar.getInstance().getTimeInMillis(), MouseEvent.BUTTON1_DOWN_MASK, mousePointer.x, mousePointer.y, MouseEvent.BUTTON1, false));
		this.mouseExited(null);

/*		SwingUtilities.invokeLater(new Runnable(){

			@Override
			public void run() {
				Point mousePointer = frame.getMousePosition(true);
				//docklet.dispatchEvent(new MouseEvent(frame, MouseEvent.MOUSE_DRAGGED, GregorianCalendar.getInstance().getTimeInMillis(), MouseEvent.BUTTON1_DOWN_MASK, mousePointer.x, mousePointer.y, MouseEvent.BUTTON1, false));
				FrameController.getInstance().mouseExited(null);
			}
		});
*/	}

	@Override
	public void dragOver(DropTargetDragEvent dtde) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void drop(DropTargetDropEvent dtde) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void dropActionChanged(DropTargetDragEvent dtde) {
		// TODO Auto-generated method stub
		
	}
	
	

}

Die Animation.java Klasse ist eigentlich zum Verständnins nicht wichtig, da sie nur einen neuen Thread öffnet in dem die Animation abgearbeitet wird. Wie gesagt über Mouse Events geht es wunderbar. Falls ihr sie doch sehen wollt einfach bescheid geben.

So... danke schonmal für jegliche Hinweise.
 
Hallo!

Ich dachte das Prinzip wäre klar geworden als ich die Animation Klasse erwähnt habe, denn die macht nicht nur ein einfaches setSize(). Wie der Name schon sagt, wird das Fenster Schritt für Schritt auf die gewünschte Größe vergrößert. Eine Animation eben. Also z.B. von 100 auf 120, aber eben alle 100 Millisekunden um 1.

Ein SwingUtilities.invokeLater() wird in der Animation Klasse realisiert. Auch das direkte zurückgeben in den EDT mit EventQueue.invokeLater() bringt das selbe Ergebnis.

Selbst wenn der Drop außerhalb des Fensters beendet wird, wird das Fenster nur teilweise auf die richtige Größe zurück animiert. Das sieht dann sehr seltsam aus.

Wenn ich dann aber einen Desktop-Link nahe des Fenster ablege, so daß er vom System unterhalb des Fensters positioniert wird, wird das Fenster wieder richtig dargestellt (neu gezeichnet?).

Es liegt irgendwie am DnD Event-Dispatching denke ich, denn wie gesagt wenn ich das ohne DnD nur mit mouseEnter() bzw. mouseExited realisiere funktioniert es wunderbar.

Weitere Ideen?
 
Hier mal noch die Animations Klassen zum Verständnis:

Animator Klasse:
Java:
import java.awt.Frame;

public class Animator {

	public static final int ANIMATE_WIDTH_ENLARGE = 0x000001;
	public static final int ANIMATE_WIDTH_SHRINK = 0x000002;
	public static final int ANIMATE_HEIGHT_ENLARGE = 0x000003;
	public static final int ANIMATE_HEIGHT_SHRINK = 0x000004;
	public static final int ANIMATE_COMPONENTS_ENLARGE = 0x000010;
	public static final int ANIMATE_COMPONENTS_SHRINK = 0x000011;
	
	private static RAnimatorSize runnable;
	static boolean isAnimating = false;

	public static void setAnimation(final int animation, Frame frame, final int value) {
		switch (animation) {
		case (Animator.ANIMATE_WIDTH_ENLARGE): {
			runnable = new RAnimatorSize(frame, value, 1);
			break;
		}
		case (Animator.ANIMATE_WIDTH_SHRINK): {
			runnable = new RAnimatorSize(frame, value, -1);
			break;
		}
		}
	}

	public static void start(final int speed, final int delay) {
		runnable.setSpeed(speed);
		runnable.setDelay(delay);
		SwingUtilities.invokeLater(runnable);

		//EventQueue.invokeLater(runnable);
		//Thread thread = new Thread(runnable);
		//thread.start();
	}

	public static boolean isAnimating() {
		return Animator.isAnimating;
	}

}

und die RAnimatorSize Klasse:
Java:
import java.awt.Frame;

public class RAnimatorSize implements Runnable {

	private int delay;
	private int speed;
	private Frame window;
	private int width;
	private int step;

	public RAnimatorSize(Frame frame, final int width, final int step) {
		this.window = frame;
		this.width = width;
		this.step = step;
	}

	public void setDelay(final int delay) {
		this.delay = delay;
	}

	public void setSpeed(final int speed) {
		this.speed = speed;
	}

	public void run() {
		Animator.isAnimating = true;
		synchronized (this) {
			try {
				this.wait(delay);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}		
		for (int counter = this.step; counter <= width;) {
			int xCoordinate = (counter % (this.step*2) == 0) ? window.getX()- this.step : window.getX();			
			window.setBounds(xCoordinate, window.getY(), window.getWidth() + this.step, window.getHeight());
			
			synchronized (this) {
				try {
					this.wait(speed);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			counter+= Math.abs(this.step);
		}
		Animator.isAnimating = false;
	}

}
 

Zurück
Oben