Visualizzazione dei risultati da 1 a 6 su 6
  1. #1
    Utente di HTML.it
    Registrato dal
    Oct 2005
    Messaggi
    25

    Effetto calamita per i JInternalFrame

    Avete idea se è possibile ricreare l' "effetto calamita" che si osserva in molti programmi quando si dispongono le loro finestre? Vorrei cercare di aggiungerlo ad un JDesktopPane che contiene molti frame interni.

  2. #2
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Te lo devi creare a mano.
    Implementare un ComponentListener che controlla se il JInternalFrame a cui è registrato raggiunge una certa distanza minima dal bordo della finestra principale. In tal caso, il JInternalFrame viene automaticamente attaccato al bordo.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  3. #3
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Questo codice che ho scritto al volo, ad esempio, crea un semplice effetto calamita quando il JInternalFrame è a 20 pixel dal bordo destro.
    codice:
    import java.awt.*;
    import javax.swing.*;
    import java.awt.event.*;
    
    public class Calamita extends JFrame {
       private class Interno extends JInternalFrame {
          public Interno() {
             setSize(300, 300);
             setTitle("Titolo");
             setVisible(true);
          }
       }
    
       private class CL extends ComponentAdapter {
          private Component p;
          public CL(Component p) { this.p = p; }
          public void componentMoved(ComponentEvent ce) {
             Component c = ce.getComponent();
             if (c.getLocation().x+c.getBounds().width >= p.getBounds().width-20) {
                c.setLocation( p.getBounds().width-c.getBounds().width-2, c.getLocation().y);
             }
             p.repaint();
          }
       }
    
       private JDesktopPane jdp;
       private Interno interno;
    
       public Calamita() {
          jdp = new JDesktopPane();
          setContentPane( jdp );
          interno = new Interno();
          interno.addComponentListener( new CL(this) );
          jdp.add( interno );
          setTitle("Titolo esterno");
          setSize(800, 600);
          setDefaultCloseOperation(EXIT_ON_CLOSE);
          setVisible(true);
       }
    
       public static void main(String [] args) {
          Calamita c = new Calamita();
       }
    }
    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  4. #4
    Utente di HTML.it
    Registrato dal
    Oct 2005
    Messaggi
    25
    Esatto! Ho capito come fare, ma rimane il problema che si vede un fastidioso susseguirsi di repaint...

    In pratica si vede il frame che viene dipinto nel suo posto originale e poi ridipinto col bordo attaccato al muro.
    Penso sia perchè prima viene chiamato il paint() normale del componente e poi viene chiamato il repaint() dal codice che hai scritto.
    Bisognerebbe impedire al componente di fare il suo paint() ad ogni movimento del mouse quando ci si trova in prossimità dei bordi... e quindi sovrascrivere qualche metodo di Component proprio?
    Ora dò un'occhiata agli API...

  5. #5
    Utente di HTML.it
    Registrato dal
    Oct 2005
    Messaggi
    25
    Ho fatto un pò di controlli e ho visto che muovendo il frame interno il metodo che viene chiamato è il repaint(). Quindi mi son concentrato su quello.

    Una possibile soluzione che ho trovato è sovrascrivere appunto il metodo di repaint() del JInternalFrame, controllando nella sua nuova implementazione se il frame si trova in prossimità del bordo.
    A quel punto se il frame si trova in prossimità del bordo, uso setLocation() e lo metto attaccato al bordo.
    Semplice! MA il problema è che setLocation chiama al suo interno il repaint()!!!!!
    Quindi si genera ricorsione indiretta, e le cose implodono in un ciclo infinito.
    Non riesco però a trovare un metodo per settare la locazione di un JInternalFrame SENZA che questo richiami il repaint()!

  6. #6
    Utente di HTML.it
    Registrato dal
    Oct 2005
    Messaggi
    25
    Yhuu penso di aver risolto. Ecco il metodo repaint() nella sua nuova implementazione. La variabile frame è il riferimento al frame principale che contiene tutto.

    codice:
    public void repaint()
          {
        	 
        	  if (frame == null)
        	  {
        		  return;
        	  }
        	  
        	  // siamo vicino al bordo
        	  if ((this.getLocation().x + this.getBounds().width >= frame.getBounds().width - 20) 
        			  &&(this.getLocation().x + this.getBounds().width <= frame.getBounds().width +20))
        	  {
        		  
        		  // se siamo proprio sul bordo
        		  if(this.getLocation().x + this.getBounds().width == frame.getBounds().width)
        		  {
        			  super.repaint();
        			  frame.repaint();
        		  }
        		  else
        		  {
        			  this.setLocation( frame.getBounds().width - this.getBounds().width, this.getLocation().y);
        		  }
        		  
        	  } // non siamo vicini al bordo 
        	  else
        	  {
        		  super.repaint();
        		  frame.repaint();
        	  }
    
          }

    Grazie a LeleFT

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.