使用unix机器文件和目录选项卡自动完成的Windows应用程序

时间:2011-12-12 14:57:21

标签: java swing unix autocomplete jcombobox

当按下“tab”时,Unix / Linux支持自动完成文件和目录。 我需要在我的Windows应用程序中创建此功能。我有一个用于文件名用户输入的文本字段,我想回复“tab”按下,就像我们在unix控制台中一样:

  1. 如果有一个选项 - 自动完成。
  2. 一些选项 - 显示选项列表。
  3. 没有选择 - nada。
  4. 对于我与unix机器的SSH连接,我使用ch.ethz.ssh API。

    有办法吗?

1 个答案:

答案 0 :(得分:2)

首先,您希望文本字段没有焦点循环和制表符抑制:

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);
        }
    }
    }
    

缺少的是显示不明确的文件名。弹出菜单会很好,不是吗?

弹出窗口:

                    // 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);