Select text in 2 JTextarea at the same time

让人想犯罪 __ 提交于 2019-12-13 20:29:35

问题


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


回答1:


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...



来源:https://stackoverflow.com/questions/22676024/select-text-in-2-jtextarea-at-the-same-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!