Text-mouseover popups sobre Swing JTextArea?

¿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 de JTextArea con una funcionalidad similar).

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 aleje. 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?

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() . Este último debería permitirle traducir la ubicación del mouse en un desplazamiento del documento.

tal vez

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

Por supuesto, la parte difícil aquí es que lo quiero en el nivel de personaje / palabra dentro del texto

Utiliza el punto del mouse para determinar dónde te encuentras 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 personaje.

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 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. (TEN EN CUENTA que deseas obtener la “ventana gráfica” del área de texto cuando calculas sobre qué se movía el cursor, si tu área de texto tiene barras de desplazamiento, la ventana gráfica solo representará el área visible en la pantalla)

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

Aquí hay una implementación real basada en @trashgods y @camickr respuesta:

con

 addToolTip(line,toolTip) 

puede agregar una información sobre herramientas para una línea específica que se mostrará cuando coloque el cursor 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 un consejo general sobre herramientas para líneas que no tienen uno específico, puede agregarlo con

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

Código 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 lineToolTips=new HashMap(); /** * 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; } }