Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 11
  1. #1

    JText-Component cambia Background Color quando ha il Focus

    Come da oggetto sarei curioso di capire come muovermi per risolvere tale problema: avere tutti JText-Component della mia applicazione con il BackGround Color (es. YELLOW) quando ricevono il Focus.

    E' preferibile:

    a) Creare da zero un nuovo componente con il settaggio del BackGround quando ricovono il Focus...

    b) Estendere i vari JText-Component con il settaggio del BackGround quando ricovono il Focus...

    c) Modificare l'UIManager (del Look&Feel) con il settaggio del BackGround quando ricovono il Focus...

    Mi sapreste indicare la corretta strada e magari anche qualche spunto in merito?

  2. #2
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328
    Nessuna delle tre.
    E' più facile creare un FocusListener e aggiungerlo a tutti i JTextComponent.

    codice:
    class MioFocusListener implements FocusListener {
       @Override
       public void focusGained(FocusEvent fe) {
          // Il text-component che ha generato l'evento ha ricevuto il focus
          JTextComponent txt = (JTextComponent) fe.getSource();
          // Coloro il background di giallo
          txt.setBackground( Color.YELLOW );
       }
    
       @Override
       public void focusLost(FocusEvent fe) {
          // Il text-component che ha generato l'evento ha perso il focus
          JTextComponent txt = (JTextComponent) fe.getSource();
          // Coloro il background di bianco
          txt.setBackground( Color.WHITE );
       }
    }
    Crei un'istanza di tale classe e la registri su tutti i tuoi JTextComponent:

    codice:
    MioFocusListener listener = new MioFocusListener();
    
    // Lo registro su una JTextField
    JTextField textField ...
    textField.addFocusListener( listener );
    
    // Lo registro su una JTextArea
    JTextArea textArea = ...
    textArea.addFocusListener( listener );
    ...
    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
    Provato ed ottimo! Non capisco però perché mi funziona su tutti i JTextComponents tranne sui JTextPane...

    Se ho ben capito, mi creo un mio listener (anziché una innerclass ho creato proprio una classe pubblica, MioFocusListener, così la uso ovunque) e lo passo a tutti i controlli testuali... uno per uno.

    Un'ulteriore domanda... ma se volessi usare due diversi BackGround, uno per i JTextField ed uno per i JTextArea... anziché creare due MioFocusListener... è possibile fare un controllo nel metodo focusGained(fe) del tipo:

    if «fe.getSource() è un JTextField» → color Yellow
    else «...è un JTextArea» → color Orange

    ?

    PS. come puoi capire sono novizio, ed anche se mi sono letto tanto materiale ho sempre una gran confusione...

  4. #4
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328
    JTextPane è un componente più complesso di un normale JTextComponent (sebbene discenda da esso). Esso deriva direttamente da JEditorPane il quale usa un sottocomponente per l'editing.

    Per la seconda domanda, sì: si può usare l'operatore instanceof per verificare se un oggetto fa parte di una determinata classe oppure no:

    codice:
    JTextComponent txt = (JTextComponent) fe.getSource();
    if (txt instanceof JTextField) {
       // E' una JTextField
    }
    
    if (txt instanceof JTextArea) {
       // E' una JTextArea
    }
    ...
    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

  5. #5
    Grazie mille Lele!

    Nella confusione più totale mi ero dimenticato dell'operatore "istanceof"...

    Certe volte mi prende lo scompenso...

    codice:
    public void focusGained(FocusEvent fe) {
             // Il text-component che ha generato l'evento ha ricevuto il focus
             Object obj = fe.getSource();
             JTextComponent txt = (JTextComponent) obj;
             // Coloro il background di giallo
             if (txt instanceof JTextField) {
                     txt.setBackground( Color.YELLOW );
             } else {
                 txt.setBackground( Color.ORANGE );
             }
    }
    Funziona a meraviglia. Ma ho un dubbio...

    Quando istanzio l'oggetto JTextComponent txt lo faccio attraverso un cast esplicito (mi pare si chiami così) di obj...

    Ma a quel punto txt non dovrebbe essere un JTextComponent? Come mai invece conserva la memoria di sapere se deriva da un JTextField o da un altro controllo JTextComponent?

    A tale riguardo ho anche provato a riscrivere l'if direttamente sull'oggetto obj (anziché su txt) e funziona...

  6. #6
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328
    Originariamente inviato da perseoclub
    Quando istanzio l'oggetto JTextComponent txt lo faccio attraverso un cast esplicito (mi pare si chiami così) di obj...

    Ma a quel punto txt non dovrebbe essere un JTextComponent? Come mai invece conserva la memoria di sapere se deriva da un JTextField o da un altro controllo JTextComponent?
    Un oggetto è sempre del tipo del quale è stato creato: un oggetto non si trasforma mai, un cast (esplicio o implicito... quello è esplicito) serve solo a "farlo vedere" come un oggetto di un altro tipo. Il metodo getSource() ritorna un Object (perchè, chiaramente, non può sapere di che tipo di oggetto si tratti). Il cast esplicito serve a farlo vedere in quel punto come un oggetto più preciso. Chiaramente, noi sappiamo che l'oggetto è un JTextComponent (non sappiamo esattamente di che tipo, ma sappiamo che è di un tipo più preciso che non un "oggetto" qualunque). Questo ci permette (e ci serve) per poter usare i metodi che quell'oggetto possiede essendo un JTextComponent, come appunto il setBackground()

    A tale riguardo ho anche provato a riscrivere l'if direttamente sull'oggetto obj (anziché su txt) e funziona...
    Certamente funziona, per il motivo visto prima... un oggetto non perde le sue caratteristiche, cambia solo il fatto che in un determinato punto del programma non si può sapere esattamente di che tipo sia tale oggetto, quindi senza il cast non si possono usare i metodi espliciti di quell'oggetto.

    Faccio un esempio più semplice (ormai è sempre quello che faccio). Se ho una gerarchia di classi che parte da una classe Figura dalla quale vengono estese le classi Cerchio, Triangolo e Rettangolo, io posso avere un metodo che lavora su un generico oggetto Figura. A tale metodo io posso passare sia un Triangolo, sia un Cerchio, sia un Rettangolo. Il metodo riceve un generico tipo Figura, ma ciò non toglie che l'oggetto reale che gli ho passato sia del tipo specifico. Come fa il metodo a usare, ad esempio, il metodo getRaggio() (che si suppone esista solamente nella classe Cerchio)? Beh... prima di tutto controllerà che l'oggetto passato sia effettivamente un Cerchio (e usa instanceof). Dopodichè, se l'oggetto passato è effettivamente un Cerchio, utilizzerà un cast esplicito a Cerchio per poterne usare il metodo getRaggio()... perchè quell'oggetto lo possiede, ma la classe Figura (sua superclasse) no.


    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

  7. #7
    Grazie ancora Lele!

    codice:
    public void focusGained(FocusEvent fe) {
             // Il text-component che ha generato l'evento ha ricevuto il focus
             JTextComponent txt = (JTextComponent)fe.getSource();
             // Coloro il background di giallo
             if (txt instanceof JTextField) {
                     txt.setBackground( Color.YELLOW );
             } else {
                 txt.setBackground( Color.ORANGE );
             }
    }
    Ipotiziamo che l'evento focusGained sia generato da un JTextField...
    Il listener però lo vede come oggetto generico finché io non lo "restringo" ad un JTextComponent txt (attraverso un casting)...
    A questo punto posso intervenire e settare i suoi metodi, tra cui il metodo setBackground.

    L'oggetto che però ha generato l'evento rimane un JTextField... e nulla vieta di utilizzare i metodi di una classe superiore perché è implicito che una classe specializzata (JTextField) li abbia ereditati dalla generica (JTextComponent).

    Ancora sono un po' confuso! Devo entrare nel meccanismo di questi passaggi logici della OOP e dei casting.
    La cosa che mi risulta ancora difficile da digerire è il perché Java è stato concepito per obbligarmi a dichiarare un casting esplicito e non per utilizzare direttamente un fe.getSource().setBackground?
    Decisamente mi sto perdendo qualche passaggio fondamentale!

  8. #8
    Utente di HTML.it
    Registrato dal
    Dec 2009
    Messaggi
    613
    Originariamente inviato da perseoclub
    Ancora sono un po' confuso! Devo entrare nel meccanismo di questi passaggi logici della OOP e dei casting.
    La cosa che mi risulta ancora difficile da digerire è il perché Java è stato concepito per obbligarmi a dichiarare un casting esplicito e non per utilizzare direttamente un fe.getSource().setBackground?
    Decisamente mi sto perdendo qualche passaggio fondamentale!
    Il metodo getSource ritorna un oggetto Object e non può che fare questo poiché a priori non può sapere che tipo di oggetto dovrà ritornare. E molto banalmente, la classe Object non possiede il metodo setBackground, quindi non puoi invocarlo su un oggetto che stai trattando come Object; devi prima avvertire il compilatore che vuoi trattare quell'oggetto come un JTextComponent: questa classe possiede il metodo che ti serve, quindi ora puoi invocarlo sull'oggetto.
    (ovviamente il compilatore "si fida" ma il casting se usato male può non andare a buon fine)

    Java tutorial sul casting (in fondo alla pagina): http://docs.oracle.com/javase/tutori...ubclasses.html

    Tutte cose che comunque aveva già detto LeleFT.

  9. #9
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328
    Originariamente inviato da perseoclub
    Ancora sono un po' confuso! Devo entrare nel meccanismo di questi passaggi logici della OOP e dei casting.
    La cosa che mi risulta ancora difficile da digerire è il perché Java è stato concepito per obbligarmi a dichiarare un casting esplicito e non per utilizzare direttamente un fe.getSource().setBackground?
    Decisamente mi sto perdendo qualche passaggio fondamentale!
    Il problema non è Java (tutti i linguaggi ObjectOriented funzionano così... ed è perfettamente logico).

    Torniamo per un attimo all'esempio delle figure.
    Un po' di codice:
    codice:
    public void lavoraConLaFigura(Figura f) {
       // Che figura mi è stata passata? Boh...
    }
    Se tu hai un oggetto Figura (e non sai nient'altro) che puoi fare? Ben poco... perchè non sai che figura sia (concretamente). Non puoi richiamare un metodo per ottenere il raggio di tale figura, perchè non puoi sapere se la figura è effettivamente un cerchio oppure un triangolo oppure ancora un rettangolo (i triangoli, come i rettangoli, non hanno un raggio, ma sono comunque figure!!).

    Io al metodo qui sopra posso passare qualunque figura:

    codice:
    Triangolo t = new Triangolo();
    Rettangolo r = new Rettangolo();
    Cerchio c = new Cerchio();
    
    lavoraConLaFigura( t );
    lavoraConLaFigura( r );
    lavoraConLaFigura( c );
    Ma lui non sa che figura gli sto passando in un determinato momento... quindi, sapendo che è comunque una Figura, lui può usare tutti i metodi che tale classe mette a disposizione.
    Se vuole usare il raggio del cerchio che gli ho passato alla terza chiamata, così com'è non può farlo... anche se ne avrebbe facoltà (perchè in concreto io gli sto dando in pasto un cerchio).

    Come si risolve? Con il cast esplicito (previo controllo, chiaramente). Il cast esplicito serve, appunto, a poter lavorare con il tipo preciso dell'oggetto passato:

    codice:
    public void lavoraConLaFigura(Figura f) {
       // Che figura mi è stata passata? Boh... controlliamo
       if (f instanceof Rettangolo) {
          Rettangolo r = (Rettangolo) f;   // E' un rettangolo... potrò farci qualcosa
       }
       if (f instanceof Triangolo) {
          Triangolo t = (Triangolo f;   // E' un triangolo... potrò farci qualcos'altro
       }
       if (f instanceof Cerchio) {
          Cerchio c = (Cerchio) f;   // E' un cerchio... posso ottenerne il raggio
       }
    }
    Questa si chiama ereditarietà: tramite l'ereditarietà una classe eredita tutto ciò che la classe base (Figura) mette a disposizione, ma in più estende le sue proprietà e i suoi comportamenti, facendogli fare qualcosa in più o qualcosa di più specifico (tralasciando per il momento il polimorfismo, per evitare troppa confusione).

    Questo non è un limite di Java: è un limite ovvio e insormontabile di qualunque linguaggio. Se in un certo punto io sto lavorando con qualcosa di generico, non posso fare altro che invocare su quell'oggetto i metodi che la classe generica mette a disposizione (perchè non posso sapere a priori che avrò a che fare con un tipo specifico piuttosto che un altro).


    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

  10. #10
    Ottimo!

    Quindi per un codice più leggibile avrei anche potuto scrivere:

    codice:
    public void lavoraConLOggettoScatenanteEvento (Oggeto obj_fe) {
        if (obj_fe instanceof JTextField) {
           JTextField a = (JTextField) obj_fe;   // E' un JTextField... potrò farci qualcosa
        }
    
        if (obj_fe instanceof JTextArea) {
           JTextArea b = (JTextArea) obj_fe;   // E' un JTextArea... potrò farci qualcos'altro
        }
    
        if (obj_fe instanceof JFormattedText) {
           JFormattedText c = (JFormattedText) obj_fe;   // E' un JFormattedText... posso farci qualcos'altro ancora
        }
     }
    Però dal momento che tutti queste 3 classi derivano (ereditarietà) da JTextComponent mi hai consigliato di fare un unico casting iniziale a JTextComponent che mi abbrevia il codice da scrivere...

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.