Как показать автозаполнение при вводе JTextArea?

Мне нужно показывать предложения (автозаполнение), когда пользователь вводит JTextArea, вроде мобильного телефона T9.

Я не знаю, как это сделать в событии myTextAreaKeyTyped().

Это приложение является помощником при наборе текста. Он показывает варианты символов, отсутствующих на клавиатуре. НАПРИМЕР. Вы нажимаете «A», он показывает Â: 1, Á: 2, À: 3… «A» будет заменен, если вы нажмете 1, 2 или 3. Это уже сделано, но варианты показаны в JLabel внизу моего JFrame, потому что я не знаю, как это сделать.

Не могли бы вы мне помочь? Заранее спасибо.


person DuckN'Bear    schedule 03.06.2012    source источник
comment
Хороший вопрос, так что вы получили до сих пор? Мы используем весь английский словарь? Или подмножество?   -  person Caffeinated    schedule 04.06.2012
comment
Конечно, это не совсем то, что вы ищете, но взгляните на демонстрацию Autocomplete от SwingLabs: swingx.java.net< /а>   -  person Rekin    schedule 04.06.2012
comment
Это приложение является помощником при наборе текста. Оно показывает варианты символов, отсутствующих на клавиатуре. Вы нажимаете A, он показывает Â:1, Á:2, À:3... 'A' будет заменено, если вы нажмете 1,2 или 3. Это уже сделано, но предложения отображаются в JLabel на внизу моего JFrame, потому что IDK, как это сделать =/   -  person DuckN'Bear    schedule 04.06.2012
comment
T9 мобильного телефона не является подсказкой, думайте об этом как о автозаполнении предложений по правописанию.   -  person Asif    schedule 04.06.2012
comment
вы можете легко переназначить для этого готовый код автозаполнения/автозаполнения.   -  person goat    schedule 04.06.2012
comment
Используйте balloontip.java.net вместо основных всплывающих подсказок, предоставляемых Swing.   -  person higuaro    schedule 04.06.2012
comment
или с помощью прослушивателя нажатия клавиш или прослушивателя документов (любого из этого) и при вводе одного слова отображать полупрозрачное всплывающее меню в той же привязке со всеми связанными словами   -  person Abhishek Choudhary    schedule 04.06.2012
comment
возможный дубликат Как реализовать автозаполнение с помощью Swing?   -  person Suraj Chandran    schedule 04.06.2012
comment
Я не думаю, что это дублирует stackoverflow.com/questions/485530/ . Им нужно автодополнение слов, это не мой случай.   -  person DuckN'Bear    schedule 05.06.2012


Ответы (1)


Вот фрагмент, чтобы вдохновиться. Вам, вероятно, потребуется немного реорганизовать код, чтобы сделать его более удобным для сопровождения, но суть должна быть понятна.

По сути, мы слушаем ключевые события (я не считаю уместным прослушивать события документа, например, если пользователь вставляет какой-то текст, я не хочу, чтобы появлялась панель предложений), и когда курсор имеет как минимум 2 символы позади, мы делаем некоторые предложения, используя всплывающее меню, содержащее JList предложений (здесь предложения действительно не имеют смысла, но было бы несложно связать это со словарем). Что касается ярлыков, о которых вы упоминаете, это не должно быть слишком сложно сделать.

import java.awt.BorderLayout;
import java.awt.Color;
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 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 Test {

    public class SuggestionPanel {
        private JList list;
        private JPopupMenu popupMenu;
        private String subWord;
        private final int insertionPosition;

        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 createSuggestionList(final int position, final String subWord) {
            Object[] data = new Object[10];
            for (int i = 0; i < data.length; i++) {
                data[i] = subWord + i;
            }
            JList list = new JList(data);
            list.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
            list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            list.setSelectedIndex(0);
            list.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (e.getClickCount() == 2) {
                        insertSelection();
                    }
                }
            });
            return list;
        }

        public boolean insertSelection() {
            if (list.getSelectedValue() != null) {
                try {
                    final String selectedSuggestion = ((String) 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);
        }

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

    private SuggestionPanel suggestion;
    private JTextArea textarea;

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

        });
    }

    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("Test frame on two screens");
        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
            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
                                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);
    }

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

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

}
person Guillaume Polet    schedule 04.06.2012