2009-06-23 8 views
1

J'ai besoin de restreindre le mouvement d'un composant (JInternalFrame) à l'intérieur d'un JPanel.
Plus précis: un composant ne doit se déplacer le long d'un axe que lorsqu'il est déplacé par l'utilisateur.Swing: Comment éviter le scintillement et la "vibration" d'un composant en limitant son mouvement?

J'ai essayé de le faire en ajoutant un écouteur de composant et de réinitialiser la position d'un axe chaque fois que le composant se déplace. Mais il "vibre" (se déplace rapidement pendant le glissement).

J'ai même écrit un gestionnaire de mise en page personnalisée, il n'a pas aidé un peu!

Je suppose que le problème est le suivant: Le gestionnaire de disposition et le programme d'écoute gèrent l'événement mouvement après le déplacement effectif du composant, n'est-ce pas?

Des suggestions?

Si (je peux) intercepter un événement, et le modifier, avant qu'il ne soit livré?

Répondre

1

vous voudrez peut-être sous-classe votre InternalFrameUI. Je vois dans BasicInteralFrameUI.BorderListener.mouseDragged(event) (ligne 885 dans la version 1.129) un appel à getDesktopManager().dragFrame(frame, newX, newY);

Vous pouvez étendre BasicInternalFrameUI retourner une coutume DesktopManager (extension de DefaultDesktopManager), où, en dragFrame() tester l'identité de votre cadre et d'ajuster l'axe.

modifier:

y penser, vous avez raison - il est trop complexe. comme l'interface utilisateur pour le cadre interne se reporte au DesktopManager du JDesktopPane, vous pouvez le définir là. voici un 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

Fonctionne parfaitement !!! –

2

Il n'y a pas "événement" que vous devez intercepter. Une fois que Swing traite l'événement souris, il indique au composant de se déplacer - et c'est là que vous pouvez ajuster les valeurs de mouvement.

déplacer, redimensionner setLocation et sont tous que des emballages à setBounds. Étendre JInternalFrame, remplacer la méthode setBounds() et ignorer la nouvelle valeur de x (ou y si vous voulez un mouvement horizontal) avant d'appeler super.setBounds().

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); 
    } 

} 

Cela devrait résoudre votre exemple, bien que regardant le code de setBounds JRE() est en fait un emballage à la méthode Reshape() dépréciée donc si vous vous sentez Reshape override courageux() à la place.

+0

Merci. Ça semble bon. La raison pour laquelle je pensais à l'interception d'événements, c'est la possibilité de faire l'alignement voulu pour n'importe quel composant. –

+0

Malheureusement, les événements sont destinés à la notification, de sorte qu'un événement de déplacement de composant est uniquement déclenché une fois que le composant a été déplacé et repeint. Pour éviter la gigue, vous devez faire votre travail avant l'événement. La seule alternative est une sorte d'écouteur mouseDragged comme suggéré par akf :) – Spyder

Questions connexes