Подтвердить что ты не робот

Текстовое всплывающее окно всплывает над Swing JTextArea?

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

возможно

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

Ответ 3

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

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

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

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

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

Ответ 4

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

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

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

Ответ 5

Вот реальная реализация, построенная на @trashgods и @camickr answer:

с

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 
 * http://stackoverflow.com/info/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;
  }
}