我正在用java创建一个记事本程序,我想实现自动关闭大括号,其中包括()、[]和{}。现在,我无法使用按键监听器检测何时按下左括号。
// called in the GUI create method
// passes in a JTextPane in the parameter
autoCloseBraces(txt);
private static void AutoCloseBraces(JTextPane txt) {
txt.addKeyListener(new KeyListener() {
@Override
public void keyPressed(KeyEvent e) {
ArrayList<Integer> keyCode = new ArrayList<Integer>();
keyCode.add(e.getKeyCode());
if (keyCode.contains(KeyEvent.VK_SHIFT) && keyCode.contains(KeyEvent.VK_9)) {
System.out.println("OK");
}
}
@Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_9) {
System.out.println("OKKKKKK");
}
}
@Override
public void keyTyped(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_9) {
System.out.println("OKK");
}
}
});
}
我还尝试使用 KeyEvent.VK_LEFT_PARENTHESIS 代替 KeyEvent.VK_9 但似乎没有任何效果。当按下“(”或“9”时,它的作用就好像只按下了“9”。不知道这里发生了什么。我也尝试在谷歌上搜索它的例子,但找不到任何东西。有人知道吗问题是或者我可以去哪里找到工作代码的解释或示例?
最佳答案
根据您想要实现的目标,这既简单又复杂,但首先,有一些“不要”:
- 如果您打算修改字段的文本,请勿使用
KeyListener
或键绑定(bind)与文本组件,当用户粘贴测试时,这些都不会被通知 - 不要使用
DocumentListener
,因为这会生成无限循环并导致Document
中出现突变异常
好的,那么你应该使用什么? DocumentFilter
,它允许您修改传递到文本组件的底层 Document
中的文本。请参阅Implementing a Document Filter了解更多详情。
下一个问题是,一般来说,作为用户,我希望您不要修改我的光标位置(除非我希望您这样做;))。现在,在这种情况下,插入 }
并将光标移动到其右侧是相当粗鲁的,因为现在我必须将光标移回原处,这只会破坏工作流量。
这是一个难题,因为 DocumentFilter
不知道文本组件(也不应该知道),因此我们需要某种方式让过滤器告诉我们它将要应用更改并已应用更改。
为此,我们可以创建一个自定义的 DocumentFilter
,它具有监听器回调功能,可以通知我们即将应用“自动完成”更改,并且已完成“自动完成”更改。这为我们提供了两个时间点,即更改之前和之后,因此我们可以获取控制光标所需的信息...
public interface AutoCompleteListener {
public void willAutoComplete(SyntaxFilter filter);
public void didAutoComplete(SyntaxFilter filter);
}
public class SyntaxFilter extends DocumentFilter {
private List<AutoCompleteListener> listeners;
public SyntaxFilter() {
listeners = new ArrayList<>(25);
}
public void addAutoCompleteListener(AutoCompleteListener listener) {
listeners.add(listener);
}
public void removeAutoCompleteListener(AutoCompleteListener listener) {
listeners.add(listener);
}
protected void fireWillAutoComplete() {
for (AutoCompleteListener listener : listeners) {
listener.willAutoComplete(this);
}
}
protected void fireDidAutoComplete() {
for (AutoCompleteListener listener : listeners) {
listener.didAutoComplete(this);
}
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
super.replace(fb, offset, length, text, attrs); //To change body of generated methods, choose Tools | Templates.
if (text.endsWith("{")) {
fireWillAutoComplete();
fb.insertString(fb.getDocument().getLength(), "}", attrs);
fireDidAutoComplete();
}
}
}
现在,我可以想到几种方法来控制光标位置,您可以简单地在更改之前获取当前位置并在更改后重置它,这会起作用,但您可能会发现它会生成一个小的当光标在该位置上移动时渲染轻弹。另一种方法是在发生更新时停止移动光标,例如...
JTextArea editor = new JTextArea(10, 20);
SyntaxFilter filter = new SyntaxFilter();
filter.addAutoCompleteListener(new AutoCompleteListener() {
private int updatePolicy = DefaultCaret.UPDATE_WHEN_ON_EDT;
@Override
public void willAutoComplete(SyntaxFilter filter) {
updatePolicy = ((DefaultCaret) editor.getCaret()).getUpdatePolicy();
((DefaultCaret) editor.getCaret()).setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
}
@Override
public void didAutoComplete(SyntaxFilter filter) {
((DefaultCaret) editor.getCaret()).setUpdatePolicy(updatePolicy);
}
});
((AbstractDocument) editor.getDocument()).setDocumentFilter(filter);
关于Java使用KeyListener检查括号是否被按下,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31661877/