2009-06-23 5 views
1

Ich muss die Bewegung einer Komponente (JInternalFrame) in einem JPanel beschränken.
Genauer: Eine Komponente sollte sich nur entlang einer Achse bewegen, wenn sie vom Benutzer gezogen wird.Swing: Wie kann ich das Flackern und "Vibrieren" einer Komponente verhindern, wenn ich ihre Bewegung einschränke?

Ich habe versucht, dies zu tun, indem ich einen Komponenten-Listener hinzufüge und die Position einer Achse jedes Mal zurücksetzt, wenn sich die Komponente bewegt. Aber es "vibriert" (bewegt sich schnell beim Ziehen).

Ich schrieb sogar einen benutzerdefinierten Layout-Manager, es hat nicht ein wenig geholfen!

Ich denke, das Problem ist: Sowohl der Layout-Manager und der Listener behandeln das Bewegungsereignis, nachdem die Komponente tatsächlich bewegt wurde, richtig?

Irgendwelche Vorschläge?

Sollte (kann ich) irgendein Ereignis abfangen und modifizieren, bevor es geliefert wird?

Antwort

1

möchten Sie möglicherweise Ihre InternalFrameUI Unterklasse. Ich sehe in BasicInteralFrameUI.BorderListener.mouseDragged(event) (Linie 885 in der Version 1.129) einen Aufruf getDesktopManager().dragFrame(frame, newX, newY);

Sie BasicInternalFrameUI verlängern könnte eine benutzerdefinierte DesktopManager (Verlängerung des DefaultDesktopManager) zurückzukehren, wo in dragFrame() Sie die Identität Ihres Rahmens testen und die Achse einzustellen.

edit:

darüber nachzudenken, Sie haben Recht - es ist zu komplex. Da die UI für den internen Frame auf die DesktopManager der JDesktopPane verweist, können Sie sie dort einstellen. hier ist ein poc:

public Demo() { 
     JFrame frame = new JFrame(); 
     frame.setSize(300,300); 
     JDesktopPane df = new JDesktopPane(); 
     DesktopManager dm = df.getDesktopManager(); 
     df.setDesktopManager(new DefaultDesktopManager(){ 
       public void dragFrame(JComponent f, int newX, int newY) { 
        super.dragFrame(f, newX, 5); 
       } 

     }); 
     JInternalFrame jif = new JInternalFrame("test "); 
     jif.setLocation(5, 5); 
     jif.setSize(150,100); 
     jif.setVisible(true); 
     df.add(jif); 
     frame.setContentPane(df); 
     frame.setVisible(true); 
} 
+0

Funktioniert perfekt !!! –

2

Es gibt kein "Ereignis", das Sie abfangen müssen. Sobald Swing das Mausereignis verarbeitet, weist es die Komponente an, sich zu bewegen - und an dieser Stelle können Sie die Bewegungswerte optimieren.

move, setLocation und resize sind alles nur Wrapper zu setBounds. Erweitern Sie JInternalFrame, überschreiben Sie die setBounds() -Methode und ignorieren Sie den neuen Wert von x (oder y, wenn Sie eine horizontale Bewegung wünschen), bevor Sie super.setBounds() aufrufen.

import javax.swing.JInternalFrame; 
public class VerticalOnlyFrame extends JInternalFrame { 

    public void setBounds(int x, int y, int width, int height) { 
      super.setBounds(getBounds().x, y, width, height); 
    } 

} 

Das Ihr Beispiel lösen soll, obwohl bei dem JRE Code setBounds suchen() ist eigentlich ein Wrapper um den veralteten reshape() -Methode so, wenn Sie mutig Überschreibung reshape() statt fühlen.

+0

Danke. Das klingt gut. Der Grund, warum ich über das Abfangen von Ereignissen nachgedacht habe, ist die Fähigkeit, die beabsichtigte Ausrichtung für jede Komponente durchzuführen. –

+0

Leider sind Ereignisse für Benachrichtigungen vorgesehen, sodass ein Komponentenbewegungsereignis nur ausgelöst wird, nachdem die Komponente verschoben und neu gezeichnet wurde. Um Jitter zu vermeiden, müssen Sie Ihre Arbeit vor dem Event erledigen. Die einzige Alternative ist eine Art mouseDragged Listener als akf vorgeschlagen :) – Spyder

Verwandte Themen