2011-05-10 22 views
18

¿Hay algo que le permita mostrar una pequeña ventana emergente de texto (como una información sobre herramientas) sobre palabras individuales o letras en un Swing JTextArea? (O una alternativa JTextArea con funcionalidad similar.)Ventana emergente de mouse de texto sobre Swing JTextArea?

Lo que necesito debe comportarse como una información sobre herramientas, en otras palabras, solo mostrar el texto emergente después de que el mouse haya pasado por encima de la palabra durante uno o dos segundos, y desaparecerá automáticamente una vez que el mouse se aleja Por supuesto, la parte difícil aquí es que lo quiero a nivel de personaje/palabra dentro del texto, no a nivel de componente ... ¿alguna sugerencia?

+1

@trashgod y @ Camickr lo dijo todo :-) La única desagradable sorpresa es Swing: la implementación de información sobre herramientas dependiente de la ubicación requiere la creación de subclases. Ese es un pequeño precio a pagar, en comparación con tu propio WhateverHoverManager – kleopatra

Respuesta

21

Puede anular getToolTipText(Mouse Event event) según sea necesario.

Adición: JTextComponent, el padre de JTextArea proporciona información de ubicación a través de dos métodos: modelToView() y viewToModel(). El latter debería permitirle traducir la ubicación del mouse en un desplazamiento del documento.

+0

+1 por simplicidad. – MByD

+0

@ trashgod +1, pero sé que algunosComponet.dispatchEvent (SwingUtilities.convertMouseEvent (..) desde Renderer pero cómo hacerlo con TextArea + Caret – mKorbel

+0

@mKorbel: Buena pregunta. Creo que la información de ubicación en ['JTextComponent'] (http://download.oracle.com/javase/6/docs/api/javax/swing/text/JTextComponent.html) es suficiente. Para referencia, he actualizado el enlace a 'JTextComponent # getToolTipText()', que lo reemplaza en 'JComponent'. – trashgod

0

Eso suena complicado. Esto está fuera de mi cabeza y probablemente no será votado. Pero es posible que puedas hacer esto.

Suponiendo que hay algún tipo de HoverListener o algo que puede implementar, o bien tendrá que implementar un oyente de mouse y construir en su propio temporizador de espera. Pero una vez que llegas aquí, hasta el punto en que sabes que quieres mostrar una información sobre herramientas, simplemente no sabes en qué letra/palabra están. Sin embargo, estoy bastante seguro de que es posible posicionar el cursor en la pantalla. Luego, usando esta posición, es posible que pueda calcular dónde estaba el cursor dentro de TextArea y luego puede tomar el personaje. Una vez que tienes el personaje/ubicación también puedes tomar la palabra completa sin mucho más trabajo. (TENGA EN CUENTA que desea obtener la "ventana gráfica" del área de texto al calcular lo que el cursor estaba pasando; si su área de texto tiene barras de desplazamiento, la ventana gráfica solo representará el área visible en la pantalla)

Disculpe las molestias una respuesta muy prolija, pero esa es la lógica general que probaría si tuviera que tener esta funcionalidad y sé que Swing no la ofrece. Con suerte, es un buen punto de partida.

+1

, deberías agregar un MouseMotionListener al JTextArea. pero getToolTipText es mucho más simple. – MeBigFatGuy

+0

anulando la herramientaTipTexto es más simple, pero utilizando el MouseMotionListener creo que podría pasar la ubicación del cursor en sus argumentos de evento, pero también podría toolTipText. Es solo cuestión de ver qué hay y qué hay disponible, supongo. Como dije, no tenía esperanzas de obtener ningún voto, pero me gusta ofrecer algo como mínimo para estimular los jugos creativos en otras personas. – gnomed

+2

tal vez será votado, a la baja ... La creatividad es buena, pero se desperdicia en simplemente reinventar la rueda. Solo si sales con una rueda increíblemente mejorada al final del día, obtendrás el elogio. La condición previa para ese éxito es un profundo conocimiento de la rueda simple ya existente y sus limitaciones (si las hay) ... las suposiciones simples no servirán de nada. Fin del sermón :-) – kleopatra

10

quizá

import java.awt.*; 
import java.awt.event.*; 
import java.awt.font.*; 
import java.awt.geom.*; 
import javax.swing.*; 
import java.util.*; 
import javax.swing.event.*; 

public class SimplePaintSurface implements Runnable, ActionListener { 

    private static final int WIDTH = 1250; 
    private static final int HEIGHT = 800; 
    private Random random = new Random(); 
    private JFrame frame = new JFrame("SimplePaintSurface"); 
    private JPanel tableaux; 

    @Override 
    public void run() { 
     tableaux = new JPanel(null); 
     for (int i = 1500; --i >= 0;) { 
      addRandom(); 
     } 
     frame.add(tableaux, BorderLayout.CENTER); 
     JButton add = new JButton("Add"); 
     add.addActionListener(this); 
     frame.add(add, BorderLayout.SOUTH); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(WIDTH, HEIGHT); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
     tableaux.requestFocusInWindow(); 
    } 

    @Override 
    public void actionPerformed(final ActionEvent e) { 
     addRandom(); 
     tableaux.repaint(); 
    } 

    void addRandom() { 
     Letter letter = new Letter(Character.toString((char) ('a' + random.nextInt(26)))); 
     letter.setBounds(random.nextInt(WIDTH), random.nextInt(HEIGHT), 16, 16); 
     tableaux.add(letter); 
    } 

    public static void main(final String[] args) { 
     SwingUtilities.invokeLater(new SimplePaintSurface()); 
    } 
} 

class Letter extends JLabel { 

    private Font font1; 
    private Font font2; 
    private final FontRenderContext fontRenderContext1; 
    private final FontRenderContext fontRenderContext2; 

    public Letter(final String letter) { 
     super(letter); 
     setFocusable(true); 
     setBackground(Color.RED); 
     font1 = getFont(); 
     font2 = font1.deriveFont(48f); 
     fontRenderContext1 = getFontMetrics(font1).getFontRenderContext(); 
     fontRenderContext2 = getFontMetrics(font2).getFontRenderContext(); 
     MouseInputAdapter mouseHandler = new MouseInputAdapter() { 

      @Override 
      public void mouseEntered(final MouseEvent e) { 
       Letter.this.setOpaque(true); 
       setFont(font2); 
       Rectangle bounds = getBounds(); 
       Rectangle2D stringBounds = font2.getStringBounds(getText(), fontRenderContext2); 
       bounds.width = (int) stringBounds.getWidth(); 
       bounds.height = (int) stringBounds.getHeight(); 
       setBounds(bounds); 
      } 

      @Override 
      public void mouseExited(final MouseEvent e) { 
       Letter.this.setOpaque(false); 
       setFont(font1); 
       Rectangle bounds = getBounds(); 
       Rectangle2D stringBounds = font1.getStringBounds(getText(), fontRenderContext1); 
       bounds.width = (int) stringBounds.getWidth(); 
       bounds.height = (int) stringBounds.getHeight(); 
       setBounds(bounds); 
      } 
     }; 
     addMouseListener(mouseHandler); 
    } 
} 
+1

+1 por un _tour de force_! – trashgod

+0

te encanta el fragmento de código aleatorio :-) – kleopatra

10

Por supuesto, la parte difícil aquí es que yo quiero que a nivel de carácter/palabra dentro del texto

utiliza el punto de ratón para determinar dónde se encuentra en el área de texto:

int offset = textArea.viewToModel(...); 

Ahora que tiene una compensación, puede obtener el carácter o la palabra en esa ubicación. La clase Utilities tiene métodos como getWordStart() y getWordEnd().

Luego usa el método getText (...) para obtener la palabra o el carácter.

+0

+1 Gracias por verificar esto. No estaba seguro cuando le comenté a @mKorbel, e inadvertidamente pasé por alto su respuesta cuando actualicé [mío] (http://stackoverflow.com/questions/5957241/text-mouseover-popups-over-a-swing-jtextarea/5957412 # 5957412). – trashgod

0

Aquí es una implementación real construido sobre @trashgods y respuesta @camickr:

con

addToolTip(line,toolTip) 

puede agregar una información sobre herramientas para una línea específica que se mostrará cuando se pasa sobre la línea. Es posible que desee establecer debug = true para obtener una información sobre herramientas emergentes para cada ubicación.

si desea mostrar una punta de herramienta general para las líneas que no tienen una específica es posible que desee agregar con Código

addToolTip(-1,"general tool tip"). 

Fuente:

package com.bitplan.swingutil; 

import java.awt.event.MouseEvent; 
import java.util.HashMap; 
import java.util.Map; 

import javax.swing.JTextArea; 
import javax.swing.text.BadLocationException; 

/** 
* Answer for 
* http://stackoverflow.com/questions/5957241/text-mouseover-popups-over-a-swing-jtextarea/35250911#35250911 
* 
* see http://stackoverflow.com/a/35250911/1497139 
* a JTextArea that shows the current Position of the mouse as a tooltip 
* @author wf 
* 
*/ 
public class JToolTipEventTextArea extends JTextArea { 
    // make sure Eclipse doesn't show a warning 
    private static final long serialVersionUID = 1L; 

    // switch to display debugging tooltip 
    boolean debug=false; 

    /** 
    * the map of tool tips per line 
    */ 
    public Map<Integer,String> lineToolTips=new HashMap<Integer,String>(); 

    /** 
    * create me with the given rows and columns 
    * @param rows 
    * @param cols 
    */ 
    public JToolTipEventTextArea(int rows, int cols) { 
    super(rows,cols); 
    // initialize the tool tip event handling 
    this.setToolTipText(""); 
    } 

    /** 
    * add a tool tip for the given line 
    * @param line - the line number 
    * @param tooltip - 
    */ 
    public void addToolTip(int line,String tooltip) { 
    lineToolTips.put(line,tooltip); 
    } 

    /** 
    * get the ToolTipText for the given mouse event 
    * @param event - the mouse event to handle 
    */ 
    public String getToolTipText(MouseEvent event) { 
    // convert the mouse position to a model position 
    int viewToModel =viewToModel(event.getPoint()); 
    // use -1 if we do not find a line number later 
    int lineNo=-1; 
    // debug information 
    String line=" line ?"; 
    // did we get a valid view to model position? 
    if(viewToModel != -1){ 
     try { 
     // convert the modelPosition to a line number 
     lineNo = this.getLineOfOffset(viewToModel)+1; 
     // set the debug info 
     line=" line "+lineNo; 
     } catch (BadLocationException ble) { 
     // in case the line number is invalid ignore this 
     // in debug mode show the issue 
     line=ble.getMessage(); 
     } 
    } 
    // try to lookup the tool tip - will be null if the line number is invalid 
    // if you want to show a general tool tip for invalid lines you might want to 
    // add it with addToolTip(-1,"general tool tip") 
    String toolTip=this.lineToolTips.get(lineNo); 
    // if in debug mode show some info 
    if (debug) { 
     // different display whether we found a tooltip or not 
     if (toolTip==null) { 
     toolTip="no tooltip for line "+lineNo; 
     } else { 
     toolTip="tooltip: "+toolTip+" for line "+lineNo; 
     } 
     // generally we add the position info for debugging 
     toolTip+=String.format(" at %3d/%3d ",event.getX(),event.getY()); 
    } 
    // now return the tool tip as wanted 
    return toolTip; 
    } 
} 
Cuestiones relacionadas