JTextPane和JTextField之间的文本选择冲突 [英] text selection conflict between JTextPane and JTextField

查看:125
本文介绍了JTextPane和JTextField之间的文本选择冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果存在JTextField,为什么无法以编程方式选择JTextPane中的文本?我认为与焦点有关。 Thx。

Why the text in JTextPane cannot be selected programmatically if there is a JTextField present? Has something to do with focus i think. Thx.

import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.beans.PropertyChangeListener;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;

public class align extends JFrame  {

    private align() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        addPane(this, "one");
        pack();
        setVisible(true);
    }

    public static void main(String[] args) {
        align t = new align();
    }

    private void addPane(JFrame frame, String name) {

        JPanel panel = new JPanel();
        panel.setLayout(new FlowLayout(FlowLayout.LEFT));
        // if the next line is disabled, then the text is JTextPane is correctly highlighted.,,
        panel.add(makeField("line1"));

        JTextPane p = new JTextPane();
        p.setText("abcdef");
        p.setSelectionStart(2);
        p.setSelectionEnd(4);
        p.setFocusable(true);
        p.requestFocus();
        p.requestDefaultFocus();
        panel.add(p);

        frame.getContentPane().add(panel);
    }

    private JComponent makeField(String name) {
        JTextField textArea = new JTextField();
        textArea.setText(name);
        textArea.setEditable(false);

        return textArea;
    }
}






编辑:


通过在构建框架后触发按键事件来显示所选文本。更好(更长)的解决方案是使用自定义Highlighter和DocumentListener的只读TextPane,使剪贴板在Ctrl-C上保持更新。

Got it to display the selected text by firing the key event after the frame has been built. A better (longer) solution would be to have a read-only TextPane with custom Highlighter and DocumentListener that keeps the clipboard updated on Ctrl-C.

    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(
            new KeyEvent(textPane, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0, KeyEvent.VK_TAB));


推荐答案

只是为了好玩(毕竟,它是星期五: - 我跟踪了Stanislav的评论,扩展了DefaultCaret以保持选择对于未聚焦的textComponents可见。

Just for fun (after all, it's Friday :-) I followed up Stanislav's comment, extending DefaultCaret to keep the selection visible for unfocused textComponents.

基本想法


  • 支持两种选择装饰:专注选择,不专心-selection

  • 保持选择亮点的外观尽可能接近LAF默认值,归结为重新使用selectionPainter(只能通过......咳嗽,咳嗽......反射) )

  • 傻瓜相信选择始终可见

  • support two selection decorations: focused-selection, unfocused-selection
  • keep the appearance of the selection highlights as near to LAF default as possible, which boils down to re-using the selectionPainter (accessible only by ... cough, cough .. reflection)
  • fool super into believing that the selection is always visible

public static class WrappingCaret extends DefaultCaret {

    private DefaultCaret delegate;
    private HighlightPainter focusedSelectionPainter;
    private HighlightPainter unfocusedSelectionPainter;
    private boolean focusedSelectionVisible;

    public WrappingCaret(JTextComponent target) {
        installDelegate((DefaultCaret) target.getCaret());
        target.setCaret(this);
    }

    private void installDelegate(DefaultCaret delegate) {
        this.delegate = delegate;
        setBlinkRate(delegate.getBlinkRate());
    }

    private void installSelectionPainters() {
        if (delegate instanceof BasicCaret) {
            installDefaultPainters();
        } else {
            try {
                Method method = delegate.getClass().getDeclaredMethod(
                        "getSelectionPainter");
                method.setAccessible(true);
                focusedSelectionPainter = (HighlightPainter) method
                        .invoke(delegate);
                Constructor<?>[] constructors = focusedSelectionPainter
                        .getClass().getDeclaredConstructors();
                constructors[0].setAccessible(true);
                unfocusedSelectionPainter = (HighlightPainter) constructors[0]
                        .newInstance(getUnfocusedSelectionColor());
            } catch (Exception e) {
                installDefaultPainters();
            }
        }
    }

    private Color getUnfocusedSelectionColor() {
        Color first = getComponent().getSelectionColor();
        // create a reasonable unfocusedSelectionColor
        return PaintUtils.setAlpha(first, 125);
    }

    private void installDefaultPainters() {
        focusedSelectionPainter = super.getSelectionPainter();
        unfocusedSelectionPainter = new DefaultHighlightPainter(
                getUnfocusedSelectionColor());
    }

    /**
     * @inherited <p>
     */
    @Override
    public void install(JTextComponent c) {
        super.install(c);
        installSelectionPainters();
        setSelectionVisible(isSelectionVisible());
    }

    /**
     * @inherited <p>
     */
    @Override
    public void setSelectionVisible(boolean vis) {
        focusedSelectionVisible = vis;
        super.setSelectionVisible(!isSelectionVisible());
        super.setSelectionVisible(true);
    }

    /**
     * @inherited <p>
     */
    @Override
    protected HighlightPainter getSelectionPainter() {
        return focusedSelectionVisible ? focusedSelectionPainter
                : unfocusedSelectionPainter;
    }

}


享受!

这篇关于JTextPane和JTextField之间的文本选择冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆