Text-Mouseover-Popups über einer Swing-JTextArea?

Lesezeit: 8 Minuten

Gibt es etwas, mit dem Sie ein kleines Text-Popup-Fenster (wie einen Tooltip) anzeigen können? individuelle Wörter oder Buchstaben in einer Swing JTextArea? (Oder eine JTextArea-Alternative mit ähnlicher Funktionalität.)

Was ich brauche, sollte sich wie ein Tooltip verhalten, mit anderen Worten, den Popup-Text erst anzeigen, nachdem die Maus ein oder zwei Sekunden über dem Wort schwebte, und er würde automatisch verschwinden, sobald sich die Maus wegbewegt. Der knifflige Teil hier ist natürlich, dass ich es auf der Zeichen-/Wortebene im Text haben möchte, nicht auf der Komponentenebene … irgendwelche Vorschläge?

  • @trashgod und @camickr haben alles gesagt 🙂 Die einzige kleine Unannehmlichkeit ist Swing selbst: Die Implementierung von standortabhängigen Tooltips erfordert Unterklassen. Das ist ein geringer Preis im Vergleich zu einem eigenen WhateverHoverManager

    – Kleopatra

    11. Mai 11 um 8:23 Uhr

Text Mouseover Popups uber einer Swing
Müllgott

Sie können überschreiben getToolTipText(Mouse Event event) wie benötigt.

Nachtrag: JTextComponent, der Elternteil von JTextArea stellt Standortinformationen über zwei Methoden bereit: modelToView() und viewToModel(). Der Letztere sollte Sie die Mausposition in einen Dokumentversatz übersetzen lassen.

  • @ trashgod +1, aber ich kenne einige Componet.dispatchEvent (SwingUtilities.convertMouseEvent (..) von Renderer, aber wie man mit TextArea + Caret umgeht

    – mKorbel

    10. Mai 11 um 23:31 Uhr


  • @mKorbel: Gute Frage. ich Überlegen die Standortinformationen in JTextComponent ist genügend. Als Referenz habe ich den Link zu aktualisiert JTextComponent#getToolTipText(), die das in überschreibt JComponent.

    – Müllgott

    11. Mai ’11 um 0:00 Uhr


  • @mKorbel .. was bedeutet? Wie so oft verstehe ich Ihre Worte (einzeln genommen), aber nicht ihre Kombination 😉

    – Kleopatra

    11. Mai ’11 um 8:25 Uhr

  • @trashgod Ich habe ein ähnliches Problem, ich habe es überschrieben getToolTipText(MouseEvent event) in meinem JTextArea aber es wird nicht angerufen. Irgendwelche Tipps?

    – Benutzer3111525

    12. März 14 um 14:54 Uhr


  • @ user3111525: Aufrufen setToolTipText() mit einem Standardwert zum Initialisieren der ToolTipManager.

    – Müllgott

    12. März 14 um 17:59 Uhr

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

Der knifflige Teil hier ist natürlich, dass ich es auf Zeichen-/Wortebene im Text haben möchte

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

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

Jetzt, da Sie einen Offset haben, können Sie das Zeichen oder Wort an dieser Stelle erhalten. Die Utilities-Klasse hat Methoden wie getWordStart() und getWordEnd().

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

  • +1 Vielen Dank für die Bestätigung. Ich war unsicher, als ich @mKorbel kommentierte, und ich habe Ihre Antwort versehentlich übersehen, als ich meine aktualisierte.

    – Müllgott

    11. Mai ’11 um 4:31 Uhr

Text Mouseover Popups uber einer Swing
Wolfgang Fahl

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

mit

addToolTip(line,toolTip) 

Sie können einen Tooltip für eine bestimmte Zeile hinzufügen, der angezeigt wird, wenn Sie mit der Maus über die Zeile 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 Zeilen anzeigen möchten, für die es keinen speziellen gibt, möchten Sie ihn möglicherweise hinzufügen

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

Diese Lösung ist nicht zu 100% das, wonach gefragt wurde, aber ziemlich nah dran. Mit ein paar Anpassungen sollte es das ursprünglich gewünschte Ergebnis erhalten.

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

Das klingt knifflig. Das ist nur aus der Spitze meines Kopfes und wird wahrscheinlich nicht gewählt werden. Aber vielleicht schaffst du das.

Angenommen, es gibt eine Art HoverListener oder etwas, das Sie implementieren können, oder Sie müssen einen Maus-Listener implementieren und Ihren eigenen Wartezeitgeber einbauen. Aber sobald Sie an einem Punkt angelangt sind, an dem Sie wissen, dass Sie einen Tooltip anzeigen möchten, wissen Sie einfach nicht, um welchen Buchstaben / welches Wort es sich handelt. Ich bin mir jedoch ziemlich sicher, dass es möglich ist, die Cursorposition auf dem Bildschirm zu erhalten. Anhand dieser Position können Sie dann möglicherweise berechnen, wo sich der Cursor in der TextArea befand, und dann können Sie das Zeichen greifen. Sobald Sie den Charakter/Ort haben, können Sie auch das ganze Wort ohne viel mehr Arbeit erfassen. (BEACHTEN SIE, dass Sie das “Ansichtsfenster” des Textbereichs erhalten möchten, wenn Sie berechnen, worüber der Cursor schwebte. Wenn Ihr Textbereich Bildlaufleisten hat, stellt das Ansichtsfenster nur den auf dem Bildschirm sichtbaren Bereich dar.)

Entschuldigung für die sehr wortreiche Antwort, aber das ist die allgemeine Logik, die ich versuchen würde, wenn ich diese Funktionalität haben MUSS und ich weiß, dass Swing sie nicht anbietet. Hoffentlich bildet es einen anständigen Ausgangspunkt.

  • Sie müssten der JTextArea einen MouseMotionListener hinzufügen. aber getToolTipText ist viel einfacher.

    – MeBigFatGuy

    10. Mai 11 um 22:54 Uhr


  • Das Überschreiben des ToolTipText ist einfacher, aber die Verwendung des MouseMotionListener könnte meiner Meinung nach die Position des Cursors in seinen Ereignisargumenten übergeben, aber auch ToolTipText. Es geht nur darum, zu sehen, was da draußen und was verfügbar ist, denke ich. Wie gesagt, ich hatte keine Hoffnung auf Stimmen, aber ich möchte zumindest etwas bieten, um die Kreativität anderer Menschen anzuregen.

    – Gnom

    11. Mai ’11 um 0:00 Uhr

  • vielleicht wird gestimmt, nach unten … Kreativität ist gut, aber verschwendet damit, das Rad einfach neu zu erfinden. Nur wenn Sie am Ende des Tages mit einem unglaublich verbesserten Rad herauskommen, werden Sie gelobt. Voraussetzung für diesen Erfolg ist eine gründliche Kenntnis des bereits existierenden einfachen Rades und seiner Grenzen (falls vorhanden) … bloße Annahmen helfen nicht. Ende der Predigt 🙂

    – Kleopatra

    11. Mai 11 um 8:17 Uhr

  • Sie müssten der JTextArea einen MouseMotionListener hinzufügen. aber getToolTipText ist viel einfacher.

    – MeBigFatGuy

    10. Mai 11 um 22:54 Uhr


  • Das Überschreiben des ToolTipText ist einfacher, aber die Verwendung des MouseMotionListener könnte meiner Meinung nach die Position des Cursors in seinen Ereignisargumenten übergeben, aber auch ToolTipText. Es geht nur darum, zu sehen, was da draußen und was verfügbar ist, denke ich. Wie gesagt, ich hatte keine Hoffnung auf Stimmen, aber ich möchte zumindest etwas bieten, um die Kreativität anderer Menschen anzuregen.

    – Gnom

    11. Mai ’11 um 0:00 Uhr

  • vielleicht wird gestimmt, nach unten … Kreativität ist gut, aber verschwendet damit, das Rad einfach neu zu erfinden. Nur wenn Sie am Ende des Tages mit einem unglaublich verbesserten Rad herauskommen, werden Sie gelobt. Voraussetzung für diesen Erfolg ist eine gründliche Kenntnis des bereits existierenden einfachen Rades und seiner Grenzen (falls vorhanden) … bloße Annahmen helfen nicht. Ende der Predigt 🙂

    – Kleopatra

    11. Mai 11 um 8:17 Uhr

.

620410cookie-checkText-Mouseover-Popups über einer Swing-JTextArea?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy