Visualizzazione dei risultati da 1 a 4 su 4

Discussione: JTextPane e mouseevent

  1. #1
    Utente di HTML.it
    Registrato dal
    Jun 2007
    Messaggi
    636

    JTextPane e mouseevent

    Ciao a tutti
    Qualcuno sa dirmi come si fa a sottolinerare il testo presente in un jtextpanel quando il mouse ci passa sopra ?

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: JTextPane e mouseevent

    Originariamente inviato da jurij7
    Qualcuno sa dirmi come si fa a sottolinerare il testo presente in un jtextpanel quando il mouse ci passa sopra ?
    Sì, si può fare ma è una cosa non proprio banale perché bisogna tenere in considerazione svariate cose.

    Innanzitutto per ricevere notifica dei movimenti sul text pane si deve usare un MouseMotionListener. La notifica tramite invocazione di mouseMoved() indica quindi che il mouse si è mosso sul componente.

    Per sapere quale è la parola si può fare in un modo simile a quanto avevo spiegato qui: si usa viewToModel() per ottenere l'offset nel document dal Point e poi si usano i metodi getWordStart() e getWordEnd() di javax.swing.text.Utilities per ottenere l'inizio/fine della parola.

    Una volta ottenuti questi dati si può aggiungere un certo insieme di attributi (AttributeSet) usando setCharacterAttributes di StyledDocument.

    Ma non è così banale. Se mi sto muovendo restando sempre sulla stessa parola, non dovrei fare nulla ma se mi muovo su un'altra parola oppure esco fuori dal componente, dovrei togliere l'effetto di "hover" dalla parola su cui ero prima.

    Questo comporta un po' di controlli. Per getWordStart()/getWordEnd() una "parola" può essere anche uno o più spazi, quindi se passo sopra a degli spazi, non dovrei attivare l'hover. Inoltre se mi muovo sempre nel componente ma nello spazio vuoto sotto le parole (se ce n'è), come offset mi trovo al fondo, quindi è come se fossi uscito dal componente.

    In pratica si deve determinare la logica per capire quando si "entra" e quando si "esce" da una parola. Se si entra in una parola e c'era già un hover, va chiaramente tolto. Poi a questo punto si imposta l'effetto di hover sulla nuova parola aggiungendo gli attributi voluti. Ma non basta. Quando l'effetto di hover va tolto, non sarebbe corretto togliere semplicemente gli attributi di hover. Se l'effetto di hover consiste nella sottolineatura e la parola ha già di per sé delle lettere sottolineate??? Togliendo l'hover non riporterei la parola nello stato originale. Quindi vanno salvati gli attributi di ogni carattere.

    Ecco un mio esempio:

    codice:
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.text.*;
    
    public class TestFrame extends JFrame
    {
        public TestFrame ()
        {
            super ("Test Frame");
    
            setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
            setSize (300, 300);
    
            StyledDocument document = new DefaultStyledDocument ();
    
            SimpleAttributeSet attributes;
    
            try
            {
                attributes = new SimpleAttributeSet ();
                StyleConstants.setForeground (attributes, Color.RED);
                document.insertString (document.getLength (), "rosso   ", attributes);
    
                attributes = new SimpleAttributeSet ();
                StyleConstants.setUnderline (attributes, true);
                document.insertString (document.getLength (), "sotto", attributes);
                document.insertString (document.getLength (), "lineato   ", null);
    
                attributes = new SimpleAttributeSet ();
                StyleConstants.setBold (attributes, true);
                document.insertString (document.getLength (), "grassetto", attributes);
            }
            catch (BadLocationException e) { }
    
            JTextPane textPane = new JTextPane (document);
            JScrollPane scrollPane = new JScrollPane (textPane);
            getContentPane ().add (scrollPane);
    
            //---- Creo l'attributo di sottolineatura per l'hover ----
            SimpleAttributeSet hoverAttrSet = new SimpleAttributeSet ();
            StyleConstants.setUnderline (hoverAttrSet, true);
    
            //---- Creo il gestore dell'hover ----
            HoverHandler hoverHandler = new HoverHandler (textPane, document, hoverAttrSet);
    
            //---- Applico i listener al text pane ----
            textPane.addMouseListener (hoverHandler);
            textPane.addMouseMotionListener (hoverHandler);
        }
    
        public static void main (String[] args)
        {
            SwingUtilities.invokeLater (new Runnable ()
            {
                public void run ()
                {
                    TestFrame f = new TestFrame ();
                    f.setVisible (true);
                }
            });
        }
    }
    
    
    class HoverHandler implements MouseMotionListener, MouseListener
    {
        private JTextPane textPane;
        private StyledDocument styledDoc;
        private AttributeSet hoverAttrSet;
    
        private boolean hover;
        private int oldStart;
        private int oldEnd;
        private AttributeSet[] oldAttributes;
    
        public HoverHandler (JTextPane textPane, StyledDocument styledDoc, AttributeSet hoverAttrSet)
        {
            this.textPane = textPane;
            this.styledDoc = styledDoc;
            this.hoverAttrSet = hoverAttrSet;
        }
    
        public void mouseDragged (MouseEvent e) { }
    
        public void mouseMoved (MouseEvent e)
        {
            try
            {
                int pos = textPane.viewToModel (e.getPoint ());
                int start = Utilities.getWordStart (textPane, pos);
                int end = Utilities.getWordEnd (textPane, pos);
    
                if (isExited (pos, start, end))
                    exit ();
    
                if (isEntered (pos, start, end))
                    enter (start, end);
            }
            catch (Exception ex) { }
        }
    
    
        public void mouseClicked (MouseEvent e) { }
        public void mouseEntered (MouseEvent e) { }
        public void mousePressed (MouseEvent e) { }
        public void mouseReleased (MouseEvent e) { }
    
        public void mouseExited (MouseEvent e)
        {
            if (hover)
                exit ();
        }
    
        private boolean isExited (int pos, int start, int end)
        {
            return hover && (pos == styledDoc.getLength () || start != oldStart);
        }
    
        private boolean isEntered (int pos, int start, int end)
            throws BadLocationException
        {
            String str = styledDoc.getText (start, end-start);
    
            if (str.trim ().equals (""))
                return false;
    
            if (hover)
                return start != oldStart;
            else
                return pos != styledDoc.getLength ();
        }
    
        private void enter (int start, int end)
        {
            oldAttributes = new AttributeSet[end-start];
    
            for (int pos = start; pos < end; pos++)
                oldAttributes[pos-start] = styledDoc.getCharacterElement (pos).getAttributes ().copyAttributes ();
    
            styledDoc.setCharacterAttributes (start, end-start, hoverAttrSet, false);
    
            hover = true;
            oldStart = start;
            oldEnd = end;
        }
    
        private void exit ()
        {
            for (int pos = oldStart; pos < oldEnd; pos++)
                styledDoc.setCharacterAttributes (pos, 1, oldAttributes[pos-oldStart], true);
    
            hover = false;
            oldAttributes = null;
        }
    }
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it
    Registrato dal
    Jun 2007
    Messaggi
    636
    Grazie per i numerosi consigli ed aiuti.

    Ho tenuto le jlabel ed ho applicato dei mousevent con cambio del cursore del mouse in hand ed ho aggiunto anche un texttooltip...anche se non mi piace molto come soluzione, forse dovrei metterci proprio dei jbutton oppure dei bordi alle jlabel..perchè non si capisce molto che proprio su quele label è possibile cliccarci.

    Ho fatto la stessa cosa anche per un jtextarea..cioè cambio del mouse da freccia ad hand con texttooltip...ed anche li non è proprio immediato capire che ci si puo cliccare..

    non so..non mi vengono altre idee.

    Certo io son che è possibile cliccarci...ma se lo usa un altro utente?

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da jurij7
    Ho tenuto le jlabel ed ho applicato dei mousevent con cambio del cursore del mouse in hand
    Se il cursore vale per tutto il componente e per tutto il tempo, allora basta semplicemente impostare il cursore una volta sola sul componente.

    Originariamente inviato da jurij7
    oppure dei bordi alle jlabel
    Mettili pure ... c'è setBorder(). Per creare un Border ci sono vari modi ma tipicamente si usa la classe "factory" BorderFactory.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

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.