Text-Mouseover Popups Over a Swing Jtextarea

Text-mouseover popups over a Swing JTextArea?

You can override getToolTipText(Mouse Event event) as needed.

Addendum: JTextComponent, the parent of JTextArea provides location information via two methods: modelToView() and viewToModel(). The latter should let you translate the mouse location into a document offset.

Tooltip below caret position in JTextArea

Use modelToView() method of JTextArea.

Auto text formatting on JTextArea

JTextArea does not support styled text. JTextPane does.

The official tutorial should be a good start: How to Use Editor Panes and Text Panes (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Swing Components)

show letters when mouse move on letters

Use the JTextComponent's viewToModel(Point p) method to get the location in the document of the text. For example...

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class SetText extends JPanel implements MouseMotionListener {

private static final float POINTS = 40f;
JTextField textField;
private JLabel displayLabel = new JLabel(" ", SwingConstants.CENTER);

public SetText() {
textField = new JTextField("Hello world! How's it going?", 20);
textField.addMouseMotionListener(this);

// make the text bigger so easier to test
textField.setFont(textField.getFont().deriveFont(Font.BOLD, POINTS));

JLabel lbl = new JLabel("Text:");
lbl.setFont(lbl.getFont().deriveFont(Font.BOLD, POINTS));
displayLabel.setFont(displayLabel.getFont().deriveFont(Font.BOLD, POINTS));

JPanel centerPanel = new JPanel();
centerPanel.add(lbl);
centerPanel.add(displayLabel);

setLayout(new BorderLayout());
add(textField, BorderLayout.PAGE_START);
add(centerPanel, BorderLayout.CENTER);
}

public void mouseMoved(MouseEvent e) {
int location = textField.viewToModel(e.getPoint());

String text = textField.getText();
if (text.isEmpty()) {
return;
}
// if (location > 0 && location < text.length()) {
if (location >= 0 && location < text.length()) {
char c = textField.getText().charAt(location);
displayLabel.setText(String.valueOf(c));
} else if (location >= text.length()) {
displayLabel.setText(text.substring(text.length() - 1));
}
}

public void mouseDragged(MouseEvent e) {

}

public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Set Text");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SetText());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}

How to get a point value for where a word (or selection) in a JTextArea is on the screen?

You can use a JEditorPane with HTML and add Hyperlinks to any given word. Read the section from the Swing tutorial on How to Use Editor Panes for the basics to get you started.

You can then add a HyperlinkListener to respond to events when the word is clicked. Read the JEditorPane API for an example of using a HyperlinkListener.

For example, when you hover the mouse over anyGivenWord, a tooltip appears,

If you don't want to use Hyperlinks then you could control the tooltip text by overriding the getToolTipText(...) method. This method receives the MouseEvent so you can get the mouse location. You can then use the viewToModel(...) method of the JTextArea to get the offset of the mouse into the Document. Then check out the Utilities. class which will help you get the start/end offsets of the word so you can use the getText(...) method to extract the word at the current mouse location.

Which event a selection of text trigger in Java JTextArea?

I don't know about any "selection listeners" for text components (although they might be useful), but you could use a CaretListener to monitor changes to the caret position and check the selection state...

public class TestSelectionMonitor {

public static void main(String[] args) {
new TestSelectionMonitor();
}

public TestSelectionMonitor() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}

final JTextArea ta = new JTextArea();
ta.addCaretListener(new CaretListener() {
@Override
public void caretUpdate(CaretEvent e) {
int length = ta.getSelectionEnd() - ta.getSelectionStart();
System.out.println(length);
}
});

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(ta));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}

Select text in 2 JTextarea at the same time

This would be so much easier if JTextComponent supported a selection model...

Basically, what you can do is attach a ChangeListener to the JTextArea's Caret and monitor for changes to the Caret, changing the selection of the other JTextArea in response...

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;

public class MirrorTextSelection {

public static void main(String[] args) {
new MirrorTextSelection();
}

public MirrorTextSelection() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class TestPane extends JPanel {

private JTextArea left;
private JTextArea right;

private DefaultHighlighter.DefaultHighlightPainter highlightPainter;

public TestPane() {

highlightPainter = new DefaultHighlighter.DefaultHighlightPainter(UIManager.getColor("TextArea.selectionBackground"));

left = new JTextArea(20, 20);
left.setWrapStyleWord(true);
left.setLineWrap(true);
right = new JTextArea(20, 20);
right.setWrapStyleWord(true);
right.setLineWrap(true);

left.setText("I am trying to do a small app that compares two similar texts contained in 2 JTextarea. I am wondering if it's possible to select text from the first JTextarea and automatically select the text on the second JTeaxtarea (lets consider that it's guarantee that the 2 JTextarea will have the same text for now) ? Should I share events or listeners ? Thank you");
right.setText("I am trying to do a small app that compares two similar texts contained in 2 JTextarea. I am wondering if it's possible to select text from the first JTextarea and automatically select the text on the second JTeaxtarea (lets consider that it's guarantee that the 2 JTextarea will have the same text for now) ? Should I share events or listeners ? Thank you");

setLayout(new GridLayout(0, 2));

add(new JScrollPane(left));
add(new JScrollPane(right));

left.getCaret().addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
int dot = left.getCaret().getDot();
int mark = left.getCaret().getMark();

right.setCaretPosition(mark);
right.moveCaretPosition(dot);
}
});
}
}
}

Now, when you run this, you will find that the right side doesn't seem to get highlighted...what?!

The selection is changing, it's just not been rendered because the component doesn't have focus...

Instead, you could use a Highlighter to highlight the text...

private DefaultHighlighter.DefaultHighlightPainter highlightPainter;
//...
highlightPainter = new DefaultHighlighter.DefaultHighlightPainter(UIManager.getColor("TextArea.selectionBackground"));

left.getCaret().addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
int dot = left.getCaret().getDot();
int mark = left.getCaret().getMark();

right.getHighlighter().removeAllHighlights();
try {
int start = Math.min(dot, mark);
int end = Math.max(dot, mark);
right.getHighlighter().addHighlight(start, end, highlightPainter);
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
});

Okay, this is now working and you can control the background color of the highlight...

There is another alternative...We can replace the Caret of the right JTextArea with one that doesn't hide the selection when focus is lost...

public class HighlightCaret extends DefaultCaret {

@Override
public void install(JTextComponent c) {
super.install(c);
setSelectionVisible(true);
}

@Override
public void focusGained(FocusEvent e) {
JTextComponent component = getComponent();
if (component.isEnabled()) {
if (component.isEditable()) {
setVisible(true);
}
setSelectionVisible(true);
}
}

@Override
public void focusLost(FocusEvent e) {
setVisible(false);
}
}

Then we set the Caret to right...

right.setCaret(nwe HighlightCaret());

This means we don't need the Highlighter code, we can stick with the original and we get control over not only the background selection color but also the foreground selection color as well...



Related Topics



Leave a reply



Submit