Swing—— JTextArea实现简单的自动完成


 

public class TextAreaDemo extends JFrame implements DocumentListener {

private JLabel label;

private JScrollPane scrollPane;

private JTextArea textArea;

 

private static final String COMMIT_ACTION = "commit";

 

private static enum Mode {

INSERT, COMPLETION

};

 

private final List<String> words;

private Mode mode = Mode.INSERT;

 

public TextAreaDemo() {

super("TextAreaDemo");

initComponents();

 

textArea.getDocument().addDocumentListener(this);

 

InputMap im = textArea.getInputMap();

ActionMap am = textArea.getActionMap();

im.put(KeyStroke.getKeyStroke("ENTER"), COMMIT_ACTION);

am.put(COMMIT_ACTION, new CommitAction());

 

words = new ArrayList<String>(5);

words.add("spark");

words.add("special");

words.add("spectacles");

words.add("spectacular");

words.add("swing");

}

 

private void initComponents() {

label = new JLabel("尝试输入 'spectacular' 'Swing'...");

 

textArea = new JTextArea();

setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

textArea.setColumns(20);

textArea.setLineWrap(true);

textArea.setRows(5);

textArea.setWrapStyleWord(true);

 

scrollPane = new JScrollPane(textArea);

 

GroupLayout layout = new GroupLayout(getContentPane());

getContentPane().setLayout(layout);

 

// Create a parallel group for the horizontal axis

ParallelGroup hGroup = layout.createParallelGroup(GroupLayout.Alignment.LEADING);

// Create a sequential and a parallel groups

SequentialGroup h1 = layout.createSequentialGroup();

ParallelGroup h2 = layout.createParallelGroup(GroupLayout.Alignment.TRAILING);

// Add a scroll panel and a label to the parallel group h2

h2.addComponent(scrollPane, GroupLayout.Alignment.LEADING,

GroupLayout.DEFAULT_SIZE, 212, Short.MAX_VALUE);

h2.addComponent(label, GroupLayout.Alignment.LEADING,

GroupLayout.DEFAULT_SIZE, 212, Short.MAX_VALUE);

 

// Add a container gap to the sequential group h1

h1.addContainerGap();

// Add the group h2 to the group h1

h1.addGroup(h2);

h1.addContainerGap();

// Add the group h1 to hGroup

hGroup.addGroup(Alignment.TRAILING, h1);

// Create the horizontal group

layout.setHorizontalGroup(hGroup);

 

// Create a parallel group for the vertical axis

ParallelGroup vGroup = layout

.createParallelGroup(GroupLayout.Alignment.LEADING);

// Create a sequential group

SequentialGroup v1 = layout.createSequentialGroup();

// Add a container gap to the sequential group v1

v1.addContainerGap();

// Add a label to the sequential group v1

v1.addComponent(label);

v1.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED);

// Add scroll panel to the sequential group v1

v1.addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 100,

Short.MAX_VALUE);

v1.addContainerGap();

// Add the group v1 to vGroup

vGroup.addGroup(v1);

// Create the vertical group

layout.setVerticalGroup(vGroup);

pack();

}

 

// Listener methods

 

public void changedUpdate(DocumentEvent ev) {

}

 

public void removeUpdate(DocumentEvent ev) {

}

 

public void insertUpdate(DocumentEvent ev) {

if (ev.getLength() != 1) {

return;

}

 

int pos = ev.getOffset();

String content = null;

try {

content = textArea.getText(0, pos + 1);

} catch (BadLocationException e) {

e.printStackTrace();

}

 

// Find where the word starts

int w;

for (w = pos; w >= 0; w--) {

if (!Character.isLetter(content.charAt(w))) {

break;

}

}

if (pos - w < 2) {

// Too few chars

return;

}

 

String prefix = content.substring(w + 1).toLowerCase();

int n = Collections.binarySearch(words, prefix);

if (n < 0 && -n <= words.size()) {

String match = words.get(-n - 1);

if (match.startsWith(prefix)) {

// A completion is found

String completion = match.substring(pos - w);

// We cannot modify Document from within notification,

// so we submit a task that does the change later

SwingUtilities.invokeLater(new CompletionTask(completion,

pos + 1));

}

} else {

// Nothing found

mode = Mode.INSERT;

}

}

 

private class CompletionTask implements Runnable {

String completion;

int position;

 

CompletionTask(String completion, int position) {

this.completion = completion;

this.position = position;

}

 

public void run() {

textArea.insert(completion, position);

textArea.setCaretPosition(position + completion.length());

textArea.moveCaretPosition(position);

mode = Mode.COMPLETION;

}

}

 

private class CommitAction extends AbstractAction {

public void actionPerformed(ActionEvent ev) {

if (mode == Mode.COMPLETION) {

int pos = textArea.getSelectionEnd();

textArea.insert(" ", pos);

textArea.setCaretPosition(pos + 1);

mode = Mode.INSERT;

} else {

textArea.replaceSelection("\n");

}

}

}

 

public static void main(String args[]) {

SwingUtilities.invokeLater(new Runnable() {

public void run() {

// Turn off metal's use of bold fonts

UIManager.put("swing.boldMetal", Boolean.FALSE);

new TextAreaDemo().setVisible(true);

}

});

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值