Вставьте слово (текст) в JTextArea из существующего сохраненного текста при вводе - PullRequest
0 голосов
/ 30 марта 2020

Я ищу вашей помощи для решения моей проблемы, над которой я сейчас работаю.

Есть ли способ вставить слово за словом (текст) в JTextArea из существующего текста, хранящегося (например, словарь), при наборе текста в текстовой области?

Это должно быть с KeyTyped или какой-то другой техникой ...

1 Ответ

1 голос
/ 30 марта 2020

На основе исполняемого кода, предоставленного @ GuillaumePolet , расположенного в этом SO Post .

Я взял этот код и немного его изменил, чтобы он может извлечь 10 указанных c слов из файла списка слов и отобразить их во всплывающем списке рядом с текущим местоположением редактируемой каретки. Вы можете набрать sh, набрав текст, или с помощью мыши дважды щелкнуть нужное слово в отображаемом всплывающем списке, или вы можете использовать курсор и клавиши Enter, чтобы сделать то же самое.

enter image description here

Список слов, который вы используете, зависит от вас. Я просто скопировал один из inte rnet, который состоит из 124390 слов. Просто укажите в переменной dictionaryFilePath String путь и имя текстового файла словаря, который вы хотите использовать. Эта переменная находится внутри внутреннего класса SuggestionPanel . Вот весь исполняемый код:

<code>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"

* * См. * https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html * для всех поддерживаемых кодировок.
* * @param locale (Locale) The Locale файла словаря. * Это также важно для сортировки, так что * это также делается в соответствии с правильным языковым стандартом.
     *         Example: Locale.FRANCE or Locale.US;
* * / publi c void addToDictionary (String dictionaryPath, String wordToAdd, String characterEncoding, Locale locale) {if (dictionaryPath. trim (). equals ("") || wordToAdd.trim (). equals ("")) {return; } wordToAdd = wordToAdd.trim (); Строка savePath = новый файл (dictionaryPath) .getAbsolutePath (); savePath = savePath.substring (0, savePath.lastIndexOf (File.separator)) + File.separator + "tmpDictFile.txt"; try (BufferedReader reader = new BufferedReader (новый InputStreamReader (новый FileInputStream (dictionaryPath), characterEncoding))) {OutputStream os = новый FileOutputStream (savePath); // PrintWriter writer = new PrintWriter (savePath)) {try (PrintWriter writer = new PrintWriter (new OutputStreamWriter (os, characterEncoding))) {{PrintWriter writer = новый PrintWriter (savePath)) {String addwordFirstChar = wordToAdd.substring 0 ( 1); Collator collator = Collator.getInstance (локаль); collator.setStrength (Collator.PRIMARY); List wordList = new ArrayList <> (); Струнная линия; while ((line = reader.readLine ())! = null) {line = line.trim (); if (line.equals ("")) {продолжить; } 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 (линия); // Добавить в верхний регистр раздел файла ... 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 strSet = new HashSet <> (wordList); wordList.clear (); wordList.addAll (strSet); Collections.sort (wordList, подборщик); for (String wrds: wordList) {writer.println (wrds); } writer.println (линия); } 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 ()); // Добавить строчную часть файла ... while ((line = reader.readLine ())! = Null) {firstChar = line.substring (0, 1); if (collator.equals (firstChar, addwordFirstChar.toLowerCase ())) {break; } wordList.add (line); } Set strSet = new HashSet <> (wordList); wordList.clear (); wordList.addAll (strSet); Collections.sort (wordList, подборщик); 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); // Добавить в файл словаря ... while ((line = reader.readLine ())! = Null ||! FirstChar.equals (firstChar.toUpperCase ())) {firstChar = line.substring (0, 1); if (! collator.equals (firstChar, addwordFirstChar)) {break; } wordList.add (line); } Set strSet = new HashSet <> (wordList); wordList.clear (); wordList.addAll (strSet); Collections.sort (wordList, подборщик); 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 (новый файл (savePath) .exists ()) {if (новый файл (dictionaryPath) .delete ()) {if (! новый файл (savePath) .renameTo (новый файл (dictionaryPath))) {System.err. println ("Не удалось добавить слово:" + wordToAdd + "в словарь!"); }}}} @SuppressWarnings ({"CallToPrintStackTrace", "Convert2Lambda"}) publi c boolean insertSelection () {if (list.getSelectedValue ()! = Null) {try {if (list.getSelectedValue (). EqualsIgnoreC ( "добавить в словарь")) {SwingUtilities.invokeLater (new Runnable () {@Override publi c void run () { addToDictionary (dictionaryFilePath, subWord, characterEncoding, locale); }}); hideSuggestion (); textarea.requestFocus (); вернуть истину; } else {final String selectedSuggestion = list.getSelectedValue (). substring (subWord.length ()); textarea.getDocument (). insertString (inserttionPosition, selectedSuggestion, null); вернуть истину; }} catch (BadLocationException e1) {e1.printStackTrace (); } hideSuggestion (); } вернуть ложь; } publi c void moveUp () {int index = Math.min (list.getSelectedIndex () - 1, 0); selectIndex (индекс); } publi c void moveDown () {int index = Math.min (list.getSelectedIndex () + 1, list.getModel (). getSize () - 1); selectIndex (индекс); } @SuppressWarnings ("Convert2Lambda") private void selectIndex (int index) {final int position = textarea.getCaretPosition (); list.setSelectedIndex (индекс); SwingUtilities.invokeLater (new Runnable () {@Override publi c void run () {textarea.setCaretPosition (position);}}); } publi c String [] searchForWord (String dictionaryFilePath, String searchCriteria, int numberOfWordsToReturn) {// Этот метод игнорирует регистр букв! List foundList = new ArrayList <> (); // Содержать все найденные слова. // Преобразуем предоставленную строку критериев в регулярное выражение // для метода String # match (), расположенного в 'while' l oop. Строка regEx = searchCriteria.replace ("?", "."). Replace ("-", "."). Replace ("*", ". *?"). ToLowerCase (); // Используем здесь «Try With Resources» для автоматического закрытия читателя. try (BufferedReader reader = new BufferedReader (новый InputStreamReader (новый FileInputStream (dictionaryFilePath), characterEncoding))) {String line = ""; int counter = 0; while ((line = reader.readLine ())! = null) {line = line.trim (). toLowerCase (); if (line.matches (regEx)) {counter ++; foundList.add (линия); // Есть совпадение ... добавить в список. if (counter == numberOfWordsToReturn) {break; }}}} // перехват исключений (если есть). catch (FileNotFoundException ex) {System.err.println (ex); } catch (IOException ex) {System.err.println (ex); } return foundList.toArray (new String [0]); // Возвращаем массив. } publi c String getDictionaryFilePath () {return dictionaryFilePath; } publi c void setDictionaryFilePath (String dictionaryFilePath) {this.dictionaryFilePath = dictionaryFilePath; } publi c int getNumberOfWordsInList () {return numberOfWordsInList; } publi c void setNumberOfWordsInList (int numberOfWordsInList) {this.numberOfWordsInList = numberOfWordsInList; } publi c Color getColorOfList () {return colorOfList; } publi c void setColorOfList (Color colorOfList) {this.colorOfList = colorOfList; } publi c Color getColorOfListText () {return colorOfListText; } publi c void setColorOfListText (Color colorOfListText) {this.colorOfListText = colorOfListText; } publi c String getListFontName () {return listFontName; } publi c Font getListFont () {return listFont; } publi c void setListFont (Font listFont) {this.listFont = listFont; this.listFontName = listFont.getName (); this.listFontStyle = listFont.getStyle (); this.listFontSize = listFont.getSize (); } publi c void setListFontName (String listFontName) {this.listFontName = listFontName; } publi c int getListFontStyle () {return listFontStyle; } publi c void setListFontStyle (int listFontStyle) {this.listFontStyle = listFontStyle; } publi c int getListFontSize () {return listFontSize; } publi c void setListFontSize (int listFontSize) {this.listFontSize = listFontSize; } publi c String getCharacterEncoding () {return characterEncoding; } publi c void setCharacterEncoding (String characterEncoding) {this.characterEncoding = characterEncoding; } publi c Locale getLocale () {return locale; } publi c void setLocale (Locale locale) {this.locale = locale; }} личное предложение SuggestionPanel; частная JTextArea textarea; @SuppressWarnings ("Convert2Lambda") защищенный void showSuggestionLater () {SwingUtilities.invokeLater (new Runnable () {@Override publi c void run () {showSuggestion ();}}); } @SuppressWarnings ({"CallToPrintStackTrace", "Convert2Lambda"}) защищенный void showSuggestion () {hideSuggestion (); final int position = textarea.getCaretPosition (); Местоположение точки; try {location = textarea.modelToView (position) .getLocation (); } catch (BadLocationException e2) {e2.printStackTrace (); возвращение; } String text = textarea.getText (); int start = Math.max (0, позиция - 1); while (start> 0) {if (! Character.isWhitespace (text.charAt (start))) {start--; } else {start ++; перемена; }} if (start> position) {return; } final String subWord = text.substring (начало, позиция); if (subWord.length () <2) {return; } offertion = new SuggestionPanel (textarea, position, subWord, location); SwingUtilities.invokeLater (new Runnable () {@Override publi c void run () {textarea.requestFocusInWindow ();}}); } private void hideSuggestion () {if (offer!! = null) {offertion.hide (); }} защищенный void initUI () {окончательный кадр JFrame = новый JFrame (); frame.setTitle («Помощник по словам»); frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); JPanel панель = новая JPanel (новая BorderLayout ()); textarea = new JTextArea (24, 80); textarea.setBorder (BorderFactory.createLineBorder (Color.DARK_GRAY, 1)); textarea.addKeyListener (new KeyListener () {@Override @SuppressWarnings ("Convert2Lambda") publi c void keyTyped (KeyEvent e) {if (e.getKeyChar () == KeyEvent.VK_ENTER) {if (предположение! = ноль) {if (offertion.insertSelection ()) {e.consume (); final int position = textarea.getCaretPosition (); SwingUtilities.invokeLater (new Runnable () {@Override @SuppressWarnings ("CallToPrintStackTrace") publi c void run () {try {textarea.getDocument (). remove (position - 1, 1);} catch (BadLocationException e) {e.printStackTrace ();}}});}}}} @Override publi c void keyReleased (KeyEvent e) {if (e.getKeyCode () == KeyEvent.VK_DOWN && Suggestion! = Null) {Suggestion.moveDown ();} иначе if (e.getKeyCode () == KeyEvent.VK_UP && Suggestion! = null) {Suggestion.moveUp (); } else if (Character.isLetterOrDi git (e.getKeyChar ())) {showSuggestionLater (); } else if (Character.isWhitespace (e.getKeyChar ())) {hideSuggestion (); }} @Override publi c void keyPressed (KeyEvent e) {}}); panel.add (textarea, BorderLayout.CENTER); frame.add (панель); frame.pack (); frame.setVisible (истина); frame.setLocationRelativeTo (нуль); } @SuppressWarnings ({"CallToPrintStackTrace", "Convert2Lambda"}) publi c stati c void main (String [] args) {try {UIManager.setLookAndFeel (UIManager.getSystemLookAndFeelClassName) () } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {e.printStackTrace (); } SwingUtilities.invokeLater (new Runnable () {@Override publi c void run () {new WordAssist (). InitUI ();}}); }} </code>

Просто запустите новый Java проект приложения с именем WordAssist и вставьте в него этот код. Это может быть не совсем то, что вы хотите, но это должно дать вам довольно хорошее представление о том, как выполнить sh, что вы хотите.

РЕДАКТИРОВАТЬ - На основе комментария в отношении использования UTF-8 (требуется Java7 +):

Я снова изменил приведенный выше код, чтобы вы могли использовать любую кодировку символов, которая вам нравится. Просто укажите строку кодирования String, которую вы хотите использовать, в переменную-член characterEncoding String, расположенную во внутреннем классе SuggestionPanel . Кодировка "UTF-8" теперь используется по умолчанию. Читатели и писатели были изменены, чтобы приспособить любую кодировку, которую вы решите использовать.

Убедитесь, что ваш текстовый файл может соответствовать выбранной вами кодировке. Если вы хотите использовать словарь французского языка, вам следует скачать такой текстовый файл словаря и указать его полный путь к dictionaryFilePath строковой переменной-члену, расположенной во внутреннем классе SuggestionPanel .

Несколько внутренних методов Getter и Setter также были предоставлены внутри внутреннего класса SuggestionPanel . Эти установщики позволяют изменять:

  • Шрифт для списка помощников Word;
  • просто имя шрифта для списка помощников Word;
  • просто стиль шрифта (обычный, полужирный , itali c, et c) для Word Assist List;
  • просто размер шрифта для Word Assist List;
  • Цвет фона списка Word Assist;
  • Word Assist Цвет текста списка;
  • Количество слов для размещения в Списке поддержки слов;
  • Путь к файлу словаря;
  • требуемая кодировка символов для использования.

Также доступна возможность добавить неизвестных слов в ваш файл словаря. При наборе текста в JTextArea и во время ввода слово не может быть определено, и поэтому не может быть предоставлено никаких предложений, тогда будет отображено следующее предложение, дающее вам возможность добавить это слово в текущий файл словаря:

enter image description here

Слова, добавленные в файл словаря, вставляются в файл, чтобы поддерживать правильный порядок возрастания. Многие текстовые файлы словаря (или списка слов) содержат заглавную букву (обычно в начале файла), если слово, которое будет добавлено либо в верхнем регистре, либо в первой букве этого слова, будет заглавным, то это слово будет вставлено в оба верхний и нижний регистр разделов этого файла. В противном случае слово просто добавляется в нижний регистр предоставленного файла словаря. Когда слова добавляются в файл словаря, этот файл словаря изменяется на установленную вами кодировку символов (по умолчанию UTF-8).

Предоставленный код представляет собой простой отпечаток того, как вы можете выполнить sh вашу задачу. Теперь от вас ожидают, что вы самостоятельно выполните любые дополнительные требования или создадите новую публикацию SO с указанием конкретных проблем, с которыми вы столкнулись, если, конечно, это не связано непосредственно с какими-либо конкретными проблемами c. с предоставленным измененным кодом выше.

...