【问题标题】:Weird java auto complete of JTextField special caseJTextField特殊情况的奇怪java自动完成
【发布时间】:2013-03-15 02:05:22
【问题描述】:

我有一个 JTextFields 的自动完成功能,到目前为止似乎可以工作,但是出现了一个特定的子情况,如下所示:尝试插入“em”,而不是“emanuele semani”自动完成,你会得到“eanuemeli li”,它没有甚至存在于列表中(列表中只包含两项:

  1. 曼纽尔·塞马尼
  2. manuemeli li

)

我知道名字很奇怪,但是有两本书有这些名字..

import java.util.ArrayList;
import javax.swing.*;
import javax.swing.text.Document;
import AutoCompleteDocument;
import CompletionService;

public class AutoCompleteExample
{
    TitleService titleService;
    Document titleAutoCompleteDocument;
    JTextField titleField;

    private class TitleService extends CompletionService
    {
        public TitleService()
        {
            ArrayList<String> eventTitles = getBookTitles();
            for (int i = 0; eventTitles != null && i < eventTitles.size(); i++)
            {
                if (eventTitles.get(i) != null)
                {
                    data.add(eventTitles.get(i));
                }
            }
        }
    }

    public AutoCompleteExample()
    {
        JPanel panel = new JPanel();
        titleField = new JTextField();
        titleField.setColumns(50);
        panel.add(titleField);

        titleService = new TitleService();
        titleAutoCompleteDocument = new AutoCompleteDocument(titleService,
                titleField);

         JFrame frame = new JFrame();
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.add(panel);
         frame.setSize(700, 100);
         frame.setVisible(true);
         refreshCompletionServices();
    }

    public void refreshCompletionServices()
    {
        titleService = new TitleService();
        titleAutoCompleteDocument = new AutoCompleteDocument(titleService,
                titleField);
        titleField.setDocument(titleAutoCompleteDocument);
    }


    private ArrayList<String> getBookTitles()
    {
        ArrayList<String> titles = new ArrayList<>();
        titles.add("emanule semani");
        titles.add("manuemeli li");
        return titles;
    }

    public static void main(String args[])
    {
        AutoCompleteExample ex = new AutoCompleteExample();
    }
}

CompletionService.java 类是

import java.util.ArrayList;
import java.util.List;


public class CompletionService
{
    public List<String> data = new ArrayList<>();
    String autoComplete(String partialString)
    {
        String hit = null;
        for (String o : data)
        {
            if (o.toLowerCase().contains(partialString.toLowerCase()))
            {
                // CompletionService contract states that we only
                // should return completion for unique hits.
                if (hit == null)
                {
                    int index = o.toLowerCase().indexOf(partialString.toLowerCase());
                    hit = o.substring(index);
                }
                else
                {
                    if (hit.length() > o.length())
                    {
                        hit = o;
                    }
                }
            }
        }
        return hit;
    }
}

而 AUtoCompleteDocument.java 是

import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
import javax.swing.text.PlainDocument;

public class AutoCompleteDocument extends PlainDocument
{
    private static final long serialVersionUID = 1L;
    private CompletionService completionService;
    private JTextComponent documentOwner;

    public AutoCompleteDocument(CompletionService service,
            JTextComponent documentOwner)
    {
        this.completionService = service;
        this.documentOwner = documentOwner;
    }

    protected String complete(String str)
    {
        Object o = completionService.autoComplete(str);
        return o == null ? null : o.toString();
    }

    @Override
    public void insertString(int offs, String str, AttributeSet a)
            throws BadLocationException
    {
        if (str == null || str.length() == 0)
        {
            return;
        }

        String text = getText(0, offs); // Current text.
        String completion = complete(text + str);
        int length = offs + str.length();
        if (completion != null && text.length() > 0)
        {
            str = completion.substring(length - 1);
            super.insertString(offs, str, a);
            documentOwner.select(length, getLength());
        }
        else
        {
            super.insertString(offs, str, a);
        }
    }
}

【问题讨论】:

标签: java swing autocomplete jtextfield


【解决方案1】:

我的回答是关于Why to reinvent the wheel,使用

【讨论】:

  • AutoComplete JComboBox / JTextField 链接有它自己的错误(在初始完成后我无法删除并开始一个新的),当我使用标准 JTextFields 时它需要一个专门的 JTextField。装饰器需要一个完整的库来做一件非常简单的事情..
  • 退格和选择没有问题(在这两种情况下)我发布这个答案的原因,也许还有另一个问题,你在使用前对数组进行了排序
  • 不,我没有对数组进行排序。无论如何,我的自动完成是内联完成,而示例是标准完成,这对我来说还不够:(
【解决方案2】:

你应该替换

if (o.toLowerCase().contains(partialString.toLowerCase()))

if (o.toLowerCase().startsWith(partialString.toLowerCase()))

【讨论】:

  • 我想要内联自动完成.. 不是行首自动完成 :( 抱歉我应该指定..
  • 无法理解您对内联自动完成的看法。你能解释一下吗?
  • 我的示例在字符串中搜索任何匹配项并完成剩余部分,如果我输入 startsWith 我只能搜索以该单词开头的匹配项.. 如果我想搜索“哈利波特”,只需输入" 但我只记得 "Pot" 我的示例有效,而 startsWith 则要求我输入 "Har"...
猜你喜欢
  • 2012-02-15
  • 2021-11-07
  • 1970-01-01
  • 2012-01-31
  • 1970-01-01
  • 1970-01-01
  • 2012-06-06
  • 1970-01-01
  • 2017-02-08
相关资源
最近更新 更多