Unix / Linux 支持按“tab”时自动完成文件和目录。
我需要在我的 Windows 应用程序中创建此功能。我有一个用于用户输入文件名的文本字段,我想响应“制表符”按下,就像我们在 Unix 控制台中一样:
- 如果有一个选项 - 自动完成。
- 一些选项 - 显示选项列表。
- 没有选择-什么也没有。
对于与我的 unix 机器的 SSH 连接,我使用 ch.ethz.ssh API。
有办法这样做吗?
首先,您想要一个没有焦点循环和制表符抑制的文本字段:
jTextField1.setFocusCycleRoot(true);
jTextField1.setFocusTraversalKeysEnabled(false);
然后是文件的数据模型(这里是本地目录,但 SSH 也是如此):
private File dir = new File("C:/Work");
private String typedPrefix = null;
private List<String> filesWithPrefix = new ArrayList<>();
然后对 TAB 进行按键处理:
- 消费该事件。
- 获取插入符号之前的前缀以搜索文件名。
- 如果您只需要限制已找到的文件名,那么就这样做,否则物理搜索它们。
-
查找文件名中最长的公共前缀。显示那个。
private void jTextField1KeyPressed(java.awt.event.KeyEvent evt) {
System.out.println("KeyPressed " + evt);
if (evt.getKeyCode() == KeyEvent.VK_TAB) {
evt.consume();
int caretPos = jTextField1.getCaretPosition();
try {
final String newPrefix = jTextField1.getText(0, caretPos);
System.out.println("newPrefix: " + newPrefix);
if (!newPrefix.isEmpty()) {
if (typedPrefix == null || !newPrefix.startsWith(typedPrefix)) {
// Must physically reload possible values:
String[] fileNames = dir.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.startsWith(newPrefix);
}
});
filesWithPrefix.clear();
Collections.addAll(filesWithPrefix, fileNames);
typedPrefix = newPrefix;
} else {
// Can reduce prior selection:
for (ListIterator<String> it = filesWithPrefix.listIterator(); it.hasNext(); ) {
String fileName = it.next();
if (!fileName.startsWith(newPrefix)) {
it.remove();
}
}
typedPrefix = newPrefix;
}
System.out.println("filesWithPrefix: " +filesWithPrefix);
if (!filesWithPrefix.isEmpty()) {
// Find longest common prefix:
String longestCommonPrefix = null;
for (String fileName : filesWithPrefix) {
if (longestCommonPrefix == null) {
longestCommonPrefix = fileName;
} else {
while (!fileName.startsWith(longestCommonPrefix)) {
longestCommonPrefix = longestCommonPrefix.substring(0, longestCommonPrefix.length() - 1);
}
}
}
if (longestCommonPrefix.length() > typedPrefix.length()) {
jTextField1.setText(longestCommonPrefix);
jTextField1.setCaretPosition(longestCommonPrefix.length());
typedPrefix = longestCommonPrefix;
}
if (filesWithPrefix.size() > 1) {
// Show popup:
;;;
} else if (filesWithPrefix.size() == 1) {
// File selected:
System.beep();
}
}
}
} catch (BadLocationException ex) {
Logger.getLogger(TabsJFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
缺少的是不明确的文件名的显示。弹出菜单会很好,不是吗?
Popup:
// Show popup:
JPopupMenu popup = new JPopupMenu();
for (String fileName : filesWithPrefix) {
popup.add(new AbstractAction(fileName) {
@Override
public void actionPerformed(ActionEvent e) {
jTextField1.setText(e.getActionCommand());
}
});
}
Point pt = jTextField1.getCaret().getMagicCaretPosition();
popup.show(jTextField1, pt.x, pt.y + 5);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)