【问题标题】:JTextArea - selection behavior on double / triple click + moving mouseJTextArea - 双击/三次单击+移动鼠标时的选择行为
【发布时间】:2020-02-29 14:37:14
【问题描述】:

问题:当你双击JTextArea中的单词时它被标记,但是当你不释放鼠标按钮并尝试标记下一个单词时,它不是标记整个单词,而是而是单个字符。

移动鼠标(双击)时,它应该标记整个单词(不是单个字符)。这实际上是我尝试过的所有程序中的默认行为,例如:记事本、Firefox、Chrome、Word,甚至 Netbeans 等。

与三次单击相同(当按住并移动鼠标时应该标记下一行,而不是字符)。

有什么想法吗?我很难用谷歌搜索这个,但由于这是一件很常见的事情,我相信一定有一个简单的选择,或者至少有人已经有了解决方案。

示例代码:

public class TestJTextArea
 {
    public static void main(final String[] args)
    {
        final JPanel panel = new JPanel(new BorderLayout());
        panel.setPreferredSize(new Dimension(500, 500));
        panel.add(new JTextArea(), BorderLayout.CENTER);

        final JFrame frame = new JFrame("Test");
        frame.getContentPane().add(panel, BorderLayout.CENTER);
        frame.pack();
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

【问题讨论】:

  • “有什么想法吗?” 1) 仔细考虑合适的标签。 2) 发布minimal reproducible example
  • 它会影响新的JTextArea,只需将JTextArea添加到JPanel并在JFrame中显示即可。
  • "just add.." 如果您不介意在 MRE / SSCCE 中展示这一点,我为什么要(或其他任何人)?
  • 好的,添加了示例代码。谢谢! :)

标签: java swing selection jtextarea double-click


【解决方案1】:

也许你需要创建一个自定义的Caret,例如:

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

public class TestJTextArea2 {
  public Component makeUI() {
    String text = "The quick brown fox jumps over the lazy dog.";
    JTextArea textArea1 = new JTextArea("default\n" + text);
    JTextArea textArea2 = new JTextArea("setCaret\n" + text) {
      @Override public void updateUI() {
        setCaret(null);
        super.updateUI();
        Caret oldCaret = getCaret();
        int blinkRate = oldCaret.getBlinkRate();
        Caret caret = new SelectWordCaret();
        caret.setBlinkRate(blinkRate);
        setCaret(caret);
      }
    };
    JPanel p = new JPanel(new GridLayout(2, 1));
    p.add(new JScrollPane(textArea1));
    p.add(new JScrollPane(textArea2));
    return p;
  }

  public static void main(String[] args) {
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new TestJTextArea2().makeUI());
      f.setSize(320, 240);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}

class SelectWordCaret extends DefaultCaret {
  private boolean wordSelectingMode = false;
  private int p0; // = Math.min(getDot(), getMark());
  private int p1; // = Math.max(getDot(), getMark());

  @Override public void mousePressed(MouseEvent e) {
    super.mousePressed(e);
    int nclicks = e.getClickCount();
    if (SwingUtilities.isLeftMouseButton(e) && !e.isConsumed() && nclicks == 2) {
      p0 = Math.min(getDot(), getMark());
      p1 = Math.max(getDot(), getMark());
      wordSelectingMode = true;
    } else {
      wordSelectingMode = false;
    }
  }

  @Override public void mouseDragged(MouseEvent e) {
    if (wordSelectingMode && !e.isConsumed() && SwingUtilities.isLeftMouseButton(e)) {
      continuouslySelectWords(e);
    } else {
      super.mouseDragged(e);
    }
  }

  private void continuouslySelectWords(MouseEvent e) {
    Position.Bias[] biasRet = new Position.Bias[1];
    JTextComponent c = getComponent();
    int pos = c.getUI().viewToModel2D(c, e.getPoint(), biasRet);
    if(biasRet[0] == null) {
      biasRet[0] = Position.Bias.Forward;
    }
    try {
      if (p0 <= pos && pos <= p1) {
        setDot(p0);
        moveDot(p1, biasRet[0]);
      } else if (p1 < pos) {
        setDot(p0);
        moveDot(Utilities.getWordEnd(c, pos - 1), biasRet[0]);
      } else if (p0 > pos) {
        setDot(p1);
        moveDot(Utilities.getWordStart(c, pos), biasRet[0]);
      }
    } catch (BadLocationException bl) {
      UIManager.getLookAndFeel().provideErrorFeedback(c);
    }
  }
}

【讨论】:

  • 很好,我一直在寻找这个。我编辑了几个次要改进的代码,对角案例(纠正了“粘性”行为周围的空格,恰好在基本单词附近,并且在选择前方时,它在空间的开始时跳过太远的步长)
猜你喜欢
  • 1970-01-01
  • 2019-07-11
  • 1970-01-01
  • 1970-01-01
  • 2012-03-28
  • 2012-01-12
  • 2013-05-08
  • 2017-09-30
  • 1970-01-01
相关资源
最近更新 更多