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

发布于 2024-12-20 22:38:09 字数 265 浏览 6 评论 0原文

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

  1. 如果有一个选项 - 自动完成。
  2. 一些选项 - 显示选项列表。
  3. 没有选择-什么也没有。

对于与我的 unix 机器的 SSH 连接,我使用 ch.ethz.ssh API。

有办法这样做吗?

Unix / Linux support auto-complete of files and directories when pressing "tab".
I need to create this ability in my windows application. I have a text field for user input of file name, which I want to respond to a "tab" press like it will do when we're in a unix console:

  1. If there is one option - Auto-complete.
  2. Some options - show a list of the options.
  3. No options - nada.

For my SSH connection to my unix machine I use the ch.ethz.ssh API.

Is there a way to do so?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

病女 2024-12-27 22:38:09

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

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("按下按键" + evt);
    
    if (evt.getKeyCode() == KeyEvent.VK_TAB) {
        evt.consume();
    
        int caretPos = jTextField1.getCaretPosition();
        尝试 {
            最终字符串 newPrefix = jTextField1.getText(0, caretPos);
            System.out.println("newPrefix: " + newPrefix);
            if (!newPrefix.isEmpty()) {
                if (typedPrefix == null || !newPrefix.startsWith(typedPrefix)) {
                    // 必须以物理方式重新加载可能的值:
                    String[] fileNames = dir.list(new FilenameFilter() {
    
                        @覆盖
                        公共布尔接受(文件目录,字符串名称){
                            返回 name.startsWith(newPrefix);
                        }
                    });
                    filesWithPrefix.clear();
                    Collections.addAll(filesWithPrefix, fileNames);
                    类型前缀 = newPrefix;
                } 别的 {
                    // 可以减少先验选择:
                    for (ListIterator; it = filesWithPrefix.listIterator(); it.hasNext(); ) {
                        字符串文件名 = it.next();
                        if (!fileName.startsWith(newPrefix)) {
                            it.remove();
                        }
                    }
                    类型前缀 = newPrefix;
                }
                System.out.println("filesWithPrefix: " +filesWithPrefix);
                if (!filesWithPrefix.isEmpty()) {
                    // 查找最长公共前缀:
                    字符串最长公共前缀 = null;
                    for (字符串文件名:filesWithPrefix) {
                        if (longestCommonPrefix == null) {
                            最长的公共前缀 = 文件名;
                        } 别的 {
                            while (!fileName.startsWith(longestCommonPrefix)) {
                                最长的CommonPrefix = 最长的CommonPrefix.substring(0, 最长的CommonPrefix.length() - 1);
                            }
                        }
                    }
                    if (longestCommonPrefix.length() > typedPrefix.length()) {
                        jTextField1.setText(longestCommonPrefix);
                        jTextField1.setCaretPosition(longestCommonPrefix.length());
                        typedPrefix = 最长的CommonPrefix;
                    }
                    if (filesWithPrefix.size() > 1) {
                        // 显示弹出窗口:
                        ;;;
                    } else if (filesWithPrefix.size() == 1) {
                        // 选定的文件:
                        系统.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);

First you want to have a text field without focus cycling, and tab suppression:

jTextField1.setFocusCycleRoot(true);
jTextField1.setFocusTraversalKeysEnabled(false);       

Then a data model for the files (here local directory, but SSH is likewise):

private File dir = new File("C:/Work");
private String typedPrefix = null;
private List<String> filesWithPrefix = new ArrayList<>();

Then a key pressed handling for the TAB:

  • Consume the event.
  • Get the prefix upto the caret for searching file names.
  • If you merely need to restrict already found file names, so do, otherwise physical search them.
  • Look for the longest common prefix in the file names. Display that.

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

What is missing is the display of the ambiguous file names. Popup menu would be nice, wouldn't it?

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文