Text-mouseover всплывает над Swing JTextArea? - PullRequest
18 голосов
/ 11 мая 2011

Есть ли что-нибудь, что позволяет вам показывать небольшое текстовое всплывающее окно (например, всплывающую подсказку) над отдельными словами или буквами в Swing JTextArea?(Или альтернатива JTextArea с аналогичной функциональностью.)

То, что мне нужно, должно вести себя как всплывающая подсказка, другими словами, отображать всплывающий текст только после того, как мышь наведет курсор на слово на секунду или две, и это будетисчезают автоматически, как только мышь уходит.Конечно, сложность заключается в том, что я хочу, чтобы это было на уровне символов / слов в тексте, а не на уровне компонентов ... какие-либо предложения?

Ответы [ 5 ]

21 голосов
/ 11 мая 2011

Вы можете переопределить getToolTipText(Mouse Event event) при необходимости.

Приложение: JTextComponent, родительский элемент JTextArea предоставляет информацию о местоположении двумя способами: modelToView() и viewToModel(). последний должен позволять вам переводить местоположение мыши в смещение документа.

10 голосов
/ 11 мая 2011

Конечно, сложность заключается в том, что я хочу, чтобы это было на уровне символов / слов в тексте

Вы используете курсор мыши, чтобы определить, где вы находитесь в текстовой области:

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

Теперь, когда у вас есть смещение, вы можете получить символ или слово в этом месте.Класс Utilities имеет такие методы, как getWordStart () и getWordEnd ().

Затем вы используете метод getText (...), чтобы получить слово или символ.

10 голосов
/ 11 мая 2011

возможно

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);
    }
}
0 голосов
/ 07 февраля 2016

Вот фактическая реализация, построенная на ответах @trashgods и @camickr:

с

addToolTip(line,toolTip) 

вы можете добавить всплывающую подсказку для конкретной строки, которая будет отображаться при наведении курсоралиния.Возможно, вы захотите установить debug = true, чтобы получить отображение всплывающей подсказки для каждого местоположения.

, если вы хотите показать общую подсказку для строк, которые не имеют конкретной, вы можете добавить ее с помощью

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

Исходный код:

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 
 * /6574874/text-mouseover-vsplyvaet-nad-swing-jtextarea
 * 
 * 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;
  }
}
0 голосов
/ 11 мая 2011

Звучит сложно. Это просто не в моей голове и, вероятно, не получит права голоса. Но вы могли бы сделать это.

Предполагая, что есть какой-то HoverListener или что-то, что вы можете реализовать, иначе вам придется реализовать прослушиватель мыши и встроить свой собственный таймер ожидания. Но как только вы попадаете сюда, до точки, когда вы знаете, что хотите открыть всплывающую подсказку, вы просто не знаете, на какой букве / слове они написаны. Я вполне уверен, что возможно получить позицию курсора на экране. Затем, используя эту позицию, вы сможете рассчитать, где курсор находится внутри TextArea, а затем вы можете получить символ. Когда у вас есть персонаж / местоположение, вы также можете взять все слово без особой работы. (Обратите внимание, что вы хотите получить «область просмотра» текстовой области при расчете над курсором, если ваша текстовая область имеет полосы прокрутки, область просмотра будет представлять только область, видимую на экране)

Извините за очень многословный ответ, но это общая логика, которую я бы попробовал, если бы у меня была такая функциональность, и я знаю, что Swing не предлагает ее. Надеюсь, это станет хорошей отправной точкой.

...