Text-Mouseover Popups über eine Swing JTextArea?

Gibt es da draußen etwas, das es erlaubt, ein kleines Text-Popup-Fenster (wie eine QuickInfo) über einzelne Wörter oder Buchstaben in einer Swing JTextArea zu zeigen? (Oder eine JTextArea-Alternative mit ähnlicher functionalität.)

Was ich brauche, sollte sich wie ein Tooltip verhalten, also nur den Popup-Text anzeigen, nachdem die Maus für eine oder zwei Sekunden über dem Wort schwebte und nach dem Wegbewegen der Maus automatisch verschwinden würde. Natürlich ist der schwierige Teil hier, dass ich es auf der Ebene Charakter / Wort innerhalb des Textes, nicht auf der Komponentenebene will … irgendwelche Vorschläge?

Sie können getToolTipText(Mouse Event event) nach Bedarf überschreiben.

Addendum: JTextComponent , das übergeordnete JTextArea von JTextArea liefert Standortinformationen über zwei Methoden: modelToView() und viewToModel() . Letzteres sollte Ihnen ermöglichen, die Mausposition in einen Dokumentenoffset zu übersetzen.

könnte sein

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

Natürlich ist der schwierige Teil hier, dass ich es auf der Zeichen- / Wortebene innerhalb des Textes haben möchte

Mit dem Mauszeiger bestimmen Sie, wo Sie sich im Textbereich befinden:

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

Jetzt, wo Sie einen Offset haben, können Sie das Zeichen oder Wort an diesem Ort bekommen. Die Utilities-class hat Methoden wie getWordStart () und getWordEnd ().

Dann verwenden Sie die Methode getText (…), um das Wort oder das Zeichen zu erhalten.

Das klingt knifflig. Dies ist nur von der Spitze meines Kopfes und wahrscheinlich nicht gewählt werden. Aber Sie könnten das vielleicht tun.

Angenommen, es gibt eine Art HoverListener oder etwas, das Sie implementieren können, oder Sie müssen einen Maus-Listener implementieren und einen eigenen Wartetimer erstellen. Aber sobald du hier bist, bis zu dem Punkt, an dem du weißt, dass du einen Tooltip aufrufen willst, weißt du nicht, auf welchem ​​Buchstaben / Wort sie sich befinden. Ich bin mir aber ziemlich sicher, dass es möglich ist, die Cursorposition auf dem Bildschirm zu bekommen. Dann können Sie anhand dieser Position berechnen, wo sich der Cursor in der TextArea befand, und dann können Sie das Zeichen abrufen. Sobald Sie den Charakter / Ort haben, können Sie auch das ganze Wort ohne viel mehr Arbeit ergreifen. (BEACHTEN SIE, dass Sie das “Ansichtsfenster” des Textbereichs erhalten möchten, wenn Sie berechnen, um was der Mauszeiger herumlag, wenn Ihr Textbereich Bildlaufleisten hat, zeigt das Ansichtsfenster nur den auf dem Bildschirm sichtbaren Bereich an)

Sorry für die sehr wortreiche Antwort, aber das ist die allgemeine Logik, die ich versuchen würde, wenn ich diese functionalität hätte und ich weiß, dass Swing es nicht anbietet. Hoffentlich macht es einen guten Startpunkt.

Hier ist eine tatsächliche Implementierung, die auf @trashgods und @camickr basiert:

mit

 addToolTip(line,toolTip) 

Sie können eine QuickInfo für eine bestimmte Zeile hinzufügen, die angezeigt wird, wenn Sie mit der Maus über die Linie fahren. Vielleicht möchten Sie debug = true setzen, um eine Tooltip-Anzeige für jeden Standort zu erhalten.

Wenn Sie einen allgemeinen Tooltip für Linien anzeigen möchten, die nicht über eine bestimmte verfügen, möchten Sie sie möglicherweise hinzufügen

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

Quellcode:

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