在JTextArea中插入字(文本),从存储的现有文本中,同时输入

问题描述 投票:0回答:1

我希望您能帮助我解决我目前正在研究的问题。

有没有一种方法可以将一个字一个字(文本)插入到 JTextArea 从现有的文本存储(如字典),同时在文本区域输入?

应该是用 KeyTyped 或其他技术...

java swing jframe jtextarea
1个回答
1
投票

根据 @GuillaumePolet 位于此 SO Post.

我把这段代码稍微修改了一下,这样它就可以从单词列表文件中提取10个特定的单词,并将它们显示在编辑滑块当前位置附近的弹出列表中。你可以打完字或用鼠标从弹出的列表中双击你想要的单词,也可以用光标和回车键来做同样的事情。

enter image description here

你使用的单词列表由你决定。我只是从网上复制了一个由124390个单词组成的。只要提供 dictionaryFilePath 字符串成员变量你要使用的字典文本文件的路径和文件名。这个变量位于 建议面板 内部类。这里是整个可运行的代码。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.BadLocationException;


public class WordAssist {

public class SuggestionPanel {

    private final JList<String> list;
    private final JPopupMenu popupMenu;
    private final String subWord;
    private final int insertionPosition;

    private String dictionaryFilePath = "French_Dictionary.txt";
    private int numberOfWordsInList = 10;
    private Color colorOfList = Color.decode("#FBFEC3");  // Light-Yellow (default)
    private Color colorOfListText = Color.decode("#000000");  // Black (default)
    private String listFontName = Font.SANS_SERIF;
    private int listFontStyle = Font.PLAIN;
    private int listFontSize = 11;
    private Font listFont = new Font(listFontName, listFontStyle, listFontSize);
    private Locale locale = Locale.FRANCE;
    public String characterEncoding = "UTF-8";

    public SuggestionPanel(JTextArea textarea, int position, String subWord, Point location) {
        this.insertionPosition = position;
        this.subWord = subWord;
        popupMenu = new JPopupMenu();
        popupMenu.removeAll();
        popupMenu.setOpaque(false);
        popupMenu.setBorder(null);
        popupMenu.add(list = createSuggestionList(position, subWord), BorderLayout.CENTER);
        popupMenu.show(textarea, location.x, textarea.getBaseline(0, 0) + location.y);
    }

    public void hide() {
        popupMenu.setVisible(false);
        if (suggestion == this) {
            suggestion = null;
        }
    }

    private JList<String> createSuggestionList(final int position, final String subWord) {
        String[] data = searchForWord(dictionaryFilePath, subWord + "*", numberOfWordsInList);
        if (data.length == 0) {
            data = new String[2];
            data[0] = " : Unknown Word : ";
            data[1] = "Add To Dictionary";
        }
        JList<String> assistList = new JList<>(data);
        assistList.setFont(new Font(listFontName, listFontStyle, listFontSize));
        assistList.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
        assistList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        assistList.setBackground(colorOfList);
        assistList.setForeground(colorOfListText);
        if (data.length == 2 && data[0].equalsIgnoreCase("unknown word:")) {
            assistList.setSelectedIndex(1);
        }
        else {
            assistList.setSelectedIndex(0);
        }
        assistList.addMouseListener(new MouseAdapter() {
            @Override
            @SuppressWarnings("Convert2Lambda")
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 1 && list.getSelectedValue().equalsIgnoreCase("add to dictionary")) {
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            addToDictionary(dictionaryFilePath, subWord, characterEncoding, locale);
                        }
                    });
                    hideSuggestion();
                    textarea.requestFocus();
                }
                if (e.getClickCount() == 2) {
                    insertSelection();
                    hideSuggestion();
                    textarea.requestFocus();
                }
            }
        });
        return assistList;
    }

    /**
     * Adds the supplied word to the supplied Dictionary text file but only
     * if it doesn't already exist. The dictionary text file must be
     * formated in such a manner that each line of that file must contain
     * only one word.
     *
     * @param dictionaryPath    (String) The path and file name to the
     *                          Dictionary text file.<br>
     *
     * @param wordToAdd         (String) The word to add to dictionary.<br>
     *
     * @param characterEncoding (String) The Character encoding to use for Dictionary:<pre>
     *
     *         Example:  "UTF-8"</pre><br>
     *
     * See:
     * <b>https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html</b>
     * for all the supported Encodings.<br>
     *
     * @param locale            (Locale) The Locale of the dictionary file.
     *                          This is also important for sorting so that
     *                          it too is done according to the proper locale.<pre>
     *         Example: Locale.FRANCE or Locale.US;</pre>
     *
     */
    public void addToDictionary(String dictionaryPath, String wordToAdd, String characterEncoding, Locale locale) {
        if (dictionaryPath.trim().equals("") || wordToAdd.trim().equals("")) {
            return;
        }
        wordToAdd = wordToAdd.trim();

        String savePath = new File(dictionaryPath).getAbsolutePath();
        savePath = savePath.substring(0, savePath.lastIndexOf(File.separator))
                + File.separator + "tmpDictFile.txt";

        try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(dictionaryPath), characterEncoding))) {
            OutputStream os = new FileOutputStream(savePath);
            // PrintWriter writer = new PrintWriter(savePath)) {
            try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(os, characterEncoding))) {
                // PrintWriter writer = new PrintWriter(savePath)) {
                String addwordFirstChar = wordToAdd.substring(0, 1);

                Collator collator = Collator.getInstance(locale);
                collator.setStrength(Collator.PRIMARY);

                List<String> wordList = new ArrayList<>();
                String line;
                while ((line = reader.readLine()) != null) {
                    line = line.trim();
                    if (line.equals("")) {
                        continue;
                    }
                    String firstChar = line.substring(0, 1);
                    if (firstChar.equals(firstChar.toUpperCase())
                            && addwordFirstChar.equals(addwordFirstChar.toUpperCase())
                            && collator.equals(firstChar, addwordFirstChar)) {
                        wordList.clear();
                        wordList.add(wordToAdd);
                        wordList.add(line);
                        // Add to uppercase section of file...
                        while ((line = reader.readLine()) != null || !firstChar.equals(firstChar.toUpperCase())) {
                            firstChar = line.substring(0, 1);
                            if (firstChar.equals(firstChar.toUpperCase())
                                    && !collator.equals(firstChar, addwordFirstChar)) {
                                break;
                            }
                            wordList.add(line);
                        }
                        Set<String> strSet = new HashSet<>(wordList);
                        wordList.clear();
                        wordList.addAll(strSet);

                        Collections.sort(wordList, collator);

                        for (String wrds : wordList) {
                            writer.println(wrds);
                        }
                        writer.println(line);
                    }
                    else if (firstChar.equals(firstChar.toLowerCase())
                            && addwordFirstChar.equals(addwordFirstChar.toUpperCase())
                            && collator.equals(firstChar, addwordFirstChar.toLowerCase())) {
                        wordList.clear();
                        if (!wordList.contains(wordToAdd.toLowerCase())) {
                            wordList.add(wordToAdd.toLowerCase());
                        }
                        wordList.add(line.toLowerCase());
                        // Add to lowercase section of file...
                        while ((line = reader.readLine()) != null) {
                            firstChar = line.substring(0, 1);
                            if (collator.equals(firstChar, addwordFirstChar.toLowerCase())) {
                                break;
                            }
                            wordList.add(line);
                        }
                        Set<String> strSet = new HashSet<>(wordList);
                        wordList.clear();
                        wordList.addAll(strSet);

                        Collections.sort(wordList, collator);

                        for (String wrds : wordList) {
                            writer.println(wrds);
                        }
                        writer.println(line);
                    }
                    else if (firstChar.equals(firstChar.toLowerCase())
                            && addwordFirstChar.equals(addwordFirstChar.toLowerCase())
                            && collator.equals(firstChar, addwordFirstChar)) {
                        wordList.clear();
                        if (!wordList.contains(wordToAdd)) {
                            wordList.add(wordToAdd);
                        }
                        wordList.add(line);
                        // Add to dictionary file...
                        while ((line = reader.readLine()) != null || !firstChar.equals(firstChar.toUpperCase())) {
                            firstChar = line.substring(0, 1);
                            if (!collator.equals(firstChar, addwordFirstChar)) {
                                break;
                            }
                            wordList.add(line);
                        }
                        Set<String> strSet = new HashSet<>(wordList);
                        wordList.clear();
                        wordList.addAll(strSet);

                        Collections.sort(wordList, collator);

                        for (String wrds : wordList) {
                            writer.println(wrds);
                        }
                        writer.println(line);
                    }
                    else {
                        writer.println(line);
                    }
                }
            }
        }
        catch (FileNotFoundException ex) {
            System.err.println(ex);
        }
        catch (UnsupportedEncodingException ex) {
            System.err.println(ex);
        }
        catch (IOException ex) {
            System.err.println(ex);
        }

        if (new File(savePath).exists()) {
            if (new File(dictionaryPath).delete()) {
                if (!new File(savePath).renameTo(new File(dictionaryPath))) {
                    System.err.println("Could not add the word: " + wordToAdd
                            + " to Dictionary!");
                }
            }
        }
    }

    @SuppressWarnings({"CallToPrintStackTrace", "Convert2Lambda"})
    public boolean insertSelection() {
        if (list.getSelectedValue() != null) {
            try {
                if (list.getSelectedValue().equalsIgnoreCase("add to dictionary")) {
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            addToDictionary(dictionaryFilePath, subWord, characterEncoding, locale);
                        }
                    });
                    hideSuggestion();
                    textarea.requestFocus();
                    return true;
                }
                else {
                    final String selectedSuggestion = list.getSelectedValue().substring(subWord.length());
                    textarea.getDocument().insertString(insertionPosition, selectedSuggestion, null);
                    return true;
                }
            }
            catch (BadLocationException e1) {
                e1.printStackTrace();
            }
            hideSuggestion();
        }
        return false;
    }

    public void moveUp() {
        int index = Math.min(list.getSelectedIndex() - 1, 0);
        selectIndex(index);
    }

    public void moveDown() {
        int index = Math.min(list.getSelectedIndex() + 1, list.getModel().getSize() - 1);
        selectIndex(index);
    }

    @SuppressWarnings("Convert2Lambda")
    private void selectIndex(int index) {
        final int position = textarea.getCaretPosition();
        list.setSelectedIndex(index);
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                textarea.setCaretPosition(position);
            }
        });
    }

    public String[] searchForWord(String dictionaryFilePath, String searchCriteria, int numberOfWordsToReturn) {
        // This method ignores letter case!
        List<String> foundList = new ArrayList<>();  // To hold all found words.

        // Convert the supplied criteria string to a Regular Expression 
        // for the String#matches() method located in the 'while' loop.
        String regEx = searchCriteria.replace("?", ".").replace("-", ".").replace("*", ".*?").toLowerCase();

        // 'Try With Resources' use here to auto-close the reader.
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(dictionaryFilePath), characterEncoding))) {
            String line = "";
            int counter = 0;
            while ((line = reader.readLine()) != null) {
                line = line.trim().toLowerCase();
                if (line.matches(regEx)) {
                    counter++;
                    foundList.add(line);  // There's a match...add to the List.
                    if (counter == numberOfWordsToReturn) {
                        break;
                    }
                }
            }
        }
        // catch Exceptions (if any).
        catch (FileNotFoundException ex) {
            System.err.println(ex);
        }
        catch (IOException ex) {
            System.err.println(ex);
        }
        return foundList.toArray(new String[0]);  // Return the Array.
    }

    public String getDictionaryFilePath() {
        return dictionaryFilePath;
    }

    public void setDictionaryFilePath(String dictionaryFilePath) {
        this.dictionaryFilePath = dictionaryFilePath;
    }

    public int getNumberOfWordsInList() {
        return numberOfWordsInList;
    }

    public void setNumberOfWordsInList(int numberOfWordsInList) {
        this.numberOfWordsInList = numberOfWordsInList;
    }

    public Color getColorOfList() {
        return colorOfList;
    }

    public void setColorOfList(Color colorOfList) {
        this.colorOfList = colorOfList;
    }

    public Color getColorOfListText() {
        return colorOfListText;
    }

    public void setColorOfListText(Color colorOfListText) {
        this.colorOfListText = colorOfListText;
    }

    public String getListFontName() {
        return listFontName;
    }

    public Font getListFont() {
        return listFont;
    }

    public void setListFont(Font listFont) {
        this.listFont = listFont;
        this.listFontName = listFont.getName();
        this.listFontStyle = listFont.getStyle();
        this.listFontSize = listFont.getSize();
    }

    public void setListFontName(String listFontName) {
        this.listFontName = listFontName;
    }

    public int getListFontStyle() {
        return listFontStyle;
    }

    public void setListFontStyle(int listFontStyle) {
        this.listFontStyle = listFontStyle;
    }

    public int getListFontSize() {
        return listFontSize;
    }

    public void setListFontSize(int listFontSize) {
        this.listFontSize = listFontSize;
    }

    public String getCharacterEncoding() {
        return characterEncoding;
    }

    public void setCharacterEncoding(String characterEncoding) {
        this.characterEncoding = characterEncoding;
    }

    public Locale getLocale() {
        return locale;
    }

    public void setLocale(Locale locale) {
        this.locale = locale;
    }

}

private SuggestionPanel suggestion;
private JTextArea textarea;

@SuppressWarnings("Convert2Lambda")
protected void showSuggestionLater() {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            showSuggestion();
        }

    });
}

@SuppressWarnings({"CallToPrintStackTrace", "Convert2Lambda"})
protected void showSuggestion() {
    hideSuggestion();
    final int position = textarea.getCaretPosition();
    Point location;
    try {
        location = textarea.modelToView(position).getLocation();
    }
    catch (BadLocationException e2) {
        e2.printStackTrace();
        return;
    }
    String text = textarea.getText();
    int start = Math.max(0, position - 1);
    while (start > 0) {
        if (!Character.isWhitespace(text.charAt(start))) {
            start--;
        }
        else {
            start++;
            break;
        }
    }
    if (start > position) {
        return;
    }
    final String subWord = text.substring(start, position);
    if (subWord.length() < 2) {
        return;
    }
    suggestion = new SuggestionPanel(textarea, position, subWord, location);
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            textarea.requestFocusInWindow();
        }
    });
}

private void hideSuggestion() {
    if (suggestion != null) {
        suggestion.hide();
    }
}

protected void initUI() {
    final JFrame frame = new JFrame();
    frame.setTitle("Word Assist");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JPanel panel = new JPanel(new BorderLayout());
    textarea = new JTextArea(24, 80);
    textarea.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
    textarea.addKeyListener(new KeyListener() {

        @Override
        @SuppressWarnings("Convert2Lambda")
        public void keyTyped(KeyEvent e) {
            if (e.getKeyChar() == KeyEvent.VK_ENTER) {
                if (suggestion != null) {
                    if (suggestion.insertSelection()) {
                        e.consume();
                        final int position = textarea.getCaretPosition();
                        SwingUtilities.invokeLater(new Runnable() {
                            @Override
                            @SuppressWarnings("CallToPrintStackTrace")
                            public void run() {
                                try {
                                    textarea.getDocument().remove(position - 1, 1);
                                }
                                catch (BadLocationException e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                    }
                }
            }
        }

        @Override
        public void keyReleased(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_DOWN && suggestion != null) {
                suggestion.moveDown();
            }
            else if (e.getKeyCode() == KeyEvent.VK_UP && suggestion != null) {
                suggestion.moveUp();
            }
            else if (Character.isLetterOrDigit(e.getKeyChar())) {
                showSuggestionLater();
            }
            else if (Character.isWhitespace(e.getKeyChar())) {
                hideSuggestion();
            }
        }

        @Override
        public void keyPressed(KeyEvent e) {

        }
    });
    panel.add(textarea, BorderLayout.CENTER);
    frame.add(panel);
    frame.pack();
    frame.setVisible(true);
    frame.setLocationRelativeTo(null);
}

@SuppressWarnings({"CallToPrintStackTrace", "Convert2Lambda"})
public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    }
    catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
        e.printStackTrace();
    }
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            new WordAssist().initUI();
        }
    });
}

}

只要启动一个新的Java应用项目,名为 词助 并将这段代码粘贴进去。它可能不是你想要的,但应该给你一个很好的想法,如何实现你想要的东西。

编辑 - 根据关于使用UTF-8(需要Java7+)的评论。

我再次修改了上面的代码,这样你就可以使用任何你喜欢的字符编码。只需将你想使用的编码字符串提供给 字符编码 字符串成员变量位于 建议面板 内类。的编码。"UTF-8" 现在是默认的。读取器和写入器已被更改,以适应您决定使用的任何编码。

确保你的文本文件能够适应你选择的字符编码。如果你想使用法语词典,那么你应该下载这样的词典文本文件,并提供它的完整路径到你的文档中。dictionaryFilePath 字符串成员变量位于 建议面板 内类。

内类中还提供了多个Getter和Setter方法。建议面板 内类。这些设置器允许你改变。

  • Word辅助列表的字体。
  • 只是Word辅助列表的字体名称。
  • 只是Word辅助列表的字体样式(纯色、粗体、斜体等)。
  • 只需为Word辅助列表设置字体大小即可。
  • Word辅助列表的背景颜色。
  • 文字辅助列表的文字颜色。
  • Word Assist List的单词数量。
  • 字典文件路径。
  • 需要使用的字符编码。

能够 增加 也可以将未知的单词添加到您提供的字典文件中。当在JTextArea中键入时,在键入过程中不能确定该词,因此不能提供任何建议,那么将显示以下内容,让您选择将该词添加到当前的字典文件中。

enter image description here

添加到字典文件中的单词被插入到文件中,以保持正确的升序。许多字典(或单词表)文本文件包含一个大写部分(通常在文件的开始),如果要添加的单词是全大写或该单词的第一个字母是大写的,那么该单词将被插入到该文件的大写和小写部分。否则,该词将被添加到所提供的字典文件的小写部分。当单词被添加到字典文件中时,该字典文件将被修改为您所设置的字符编码(默认为UTF-8)。

所提供的代码仅仅是 脚印 您可能想如何完成您的任务。现在,您需要自己执行任何进一步的要求,或者,开始一个新的SO帖子,说明您遇到的具体问题,当然,除非它与上面提供的修改后的代码的任何具体问题直接相关。

© www.soinside.com 2019 - 2024. All rights reserved.