誰か答えてもらえたら、これは答えさせてください。グーグル検索エンジンのように基本的に必要です、私たちがいずれかのキーを押すと、それは表示提案関連の押されたキーになります。
SatishDhimanに関して
誰か答えてもらえたら、これは答えさせてください。グーグル検索エンジンのように基本的に必要です、私たちがいずれかのキーを押すと、それは表示提案関連の押されたキーになります。
SatishDhimanに関して
私のコメント/以前のコードから、この更新を参照してください:
で使用JTextField
するAutoSuggestor
:
(またはJTextField以外の他のJTextComponentを使用JTextArea
すると、ポップアップウィンドウがcaretの下に表示されます)AutoSuggestor
:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JWindow;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
/**
* @author David
*/
public class Test {
public Test() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//JTextField f = new JTextField(10);
JTextArea f = new JTextArea(10, 10);
//JEditorPane f = new JEditorPane();
//create words for dictionary could also use null as parameter for AutoSuggestor(..,..,null,..,..,..,..) and than call AutoSuggestor#setDictionary after AutoSuggestr insatnce has been created
ArrayList<String> words = new ArrayList<>();
words.add("hello");
words.add("heritage");
words.add("happiness");
words.add("goodbye");
words.add("cruel");
words.add("car");
words.add("war");
words.add("will");
words.add("world");
words.add("wall");
AutoSuggestor autoSuggestor = new AutoSuggestor(f, frame, words, Color.WHITE.brighter(), Color.BLUE, Color.RED, 0.75f) {
@Override
boolean wordTyped(String typedWord) {
System.out.println(typedWord);
return super.wordTyped(typedWord);//checks for a match in dictionary and returns true or false if found or not
}
};
JPanel p = new JPanel();
p.add(f);
frame.add(p);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Test();
}
});
}
}
class AutoSuggestor {
private final JTextComponent textComp;
private final Window container;
private JPanel suggestionsPanel;
private JWindow autoSuggestionPopUpWindow;
private String typedWord;
private final ArrayList<String> dictionary = new ArrayList<>();
private int currentIndexOfSpace, tW, tH;
private DocumentListener documentListener = new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent de) {
checkForAndShowSuggestions();
}
@Override
public void removeUpdate(DocumentEvent de) {
checkForAndShowSuggestions();
}
@Override
public void changedUpdate(DocumentEvent de) {
checkForAndShowSuggestions();
}
};
private final Color suggestionsTextColor;
private final Color suggestionFocusedColor;
public AutoSuggestor(JTextComponent textComp, Window mainWindow, ArrayList<String> words, Color popUpBackground, Color textColor, Color suggestionFocusedColor, float opacity) {
this.textComp = textComp;
this.suggestionsTextColor = textColor;
this.container = mainWindow;
this.suggestionFocusedColor = suggestionFocusedColor;
this.textComp.getDocument().addDocumentListener(documentListener);
setDictionary(words);
typedWord = "";
currentIndexOfSpace = 0;
tW = 0;
tH = 0;
autoSuggestionPopUpWindow = new JWindow(mainWindow);
autoSuggestionPopUpWindow.setOpacity(opacity);
suggestionsPanel = new JPanel();
suggestionsPanel.setLayout(new GridLayout(0, 1));
suggestionsPanel.setBackground(popUpBackground);
addKeyBindingToRequestFocusInPopUpWindow();
}
private void addKeyBindingToRequestFocusInPopUpWindow() {
textComp.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "Down released");
textComp.getActionMap().put("Down released", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {//focuses the first label on popwindow
for (int i = 0; i < suggestionsPanel.getComponentCount(); i++) {
if (suggestionsPanel.getComponent(i) instanceof SuggestionLabel) {
((SuggestionLabel) suggestionsPanel.getComponent(i)).setFocused(true);
autoSuggestionPopUpWindow.toFront();
autoSuggestionPopUpWindow.requestFocusInWindow();
suggestionsPanel.requestFocusInWindow();
suggestionsPanel.getComponent(i).requestFocusInWindow();
break;
}
}
}
});
suggestionsPanel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "Down released");
suggestionsPanel.getActionMap().put("Down released", new AbstractAction() {
int lastFocusableIndex = 0;
@Override
public void actionPerformed(ActionEvent ae) {//allows scrolling of labels in pop window (I know very hacky for now :))
ArrayList<SuggestionLabel> sls = getAddedSuggestionLabels();
int max = sls.size();
if (max > 1) {//more than 1 suggestion
for (int i = 0; i < max; i++) {
SuggestionLabel sl = sls.get(i);
if (sl.isFocused()) {
if (lastFocusableIndex == max - 1) {
lastFocusableIndex = 0;
sl.setFocused(false);
autoSuggestionPopUpWindow.setVisible(false);
setFocusToTextField();
checkForAndShowSuggestions();//fire method as if document listener change occured and fired it
} else {
sl.setFocused(false);
lastFocusableIndex = i;
}
} else if (lastFocusableIndex <= i) {
if (i < max) {
sl.setFocused(true);
autoSuggestionPopUpWindow.toFront();
autoSuggestionPopUpWindow.requestFocusInWindow();
suggestionsPanel.requestFocusInWindow();
suggestionsPanel.getComponent(i).requestFocusInWindow();
lastFocusableIndex = i;
break;
}
}
}
} else {//only a single suggestion was given
autoSuggestionPopUpWindow.setVisible(false);
setFocusToTextField();
checkForAndShowSuggestions();//fire method as if document listener change occured and fired it
}
}
});
}
private void setFocusToTextField() {
container.toFront();
container.requestFocusInWindow();
textComp.requestFocusInWindow();
}
public ArrayList<SuggestionLabel> getAddedSuggestionLabels() {
ArrayList<SuggestionLabel> sls = new ArrayList<>();
for (int i = 0; i < suggestionsPanel.getComponentCount(); i++) {
if (suggestionsPanel.getComponent(i) instanceof SuggestionLabel) {
SuggestionLabel sl = (SuggestionLabel) suggestionsPanel.getComponent(i);
sls.add(sl);
}
}
return sls;
}
private void checkForAndShowSuggestions() {
typedWord = getCurrentlyTypedWord();
suggestionsPanel.removeAll();//remove previos words/jlabels that were added
//used to calcualte size of JWindow as new Jlabels are added
tW = 0;
tH = 0;
boolean added = wordTyped(typedWord);
if (!added) {
if (autoSuggestionPopUpWindow.isVisible()) {
autoSuggestionPopUpWindow.setVisible(false);
}
} else {
showPopUpWindow();
setFocusToTextField();
}
}
protected void addWordToSuggestions(String word) {
SuggestionLabel suggestionLabel = new SuggestionLabel(word, suggestionFocusedColor, suggestionsTextColor, this);
calculatePopUpWindowSize(suggestionLabel);
suggestionsPanel.add(suggestionLabel);
}
public String getCurrentlyTypedWord() {//get newest word after last white spaceif any or the first word if no white spaces
String text = textComp.getText();
String wordBeingTyped = "";
text = text.replaceAll("(\\r|\\n)", " ");
if (text.contains(" ")) {
int tmp = text.lastIndexOf(" ");
if (tmp >= currentIndexOfSpace) {
currentIndexOfSpace = tmp;
wordBeingTyped = text.substring(text.lastIndexOf(" "));
}
} else {
wordBeingTyped = text;
}
return wordBeingTyped.trim();
}
private void calculatePopUpWindowSize(JLabel label) {
//so we can size the JWindow correctly
if (tW < label.getPreferredSize().width) {
tW = label.getPreferredSize().width;
}
tH += label.getPreferredSize().height;
}
private void showPopUpWindow() {
autoSuggestionPopUpWindow.getContentPane().add(suggestionsPanel);
autoSuggestionPopUpWindow.setMinimumSize(new Dimension(textComp.getWidth(), 30));
autoSuggestionPopUpWindow.setSize(tW, tH);
autoSuggestionPopUpWindow.setVisible(true);
int windowX = 0;
int windowY = 0;
if (textComp instanceof JTextField) {//calculate x and y for JWindow at bottom of JTextField
windowX = container.getX() + textComp.getX() + 5;
if (suggestionsPanel.getHeight() > autoSuggestionPopUpWindow.getMinimumSize().height) {
windowY = container.getY() + textComp.getY() + textComp.getHeight() + autoSuggestionPopUpWindow.getMinimumSize().height;
} else {
windowY = container.getY() + textComp.getY() + textComp.getHeight() + autoSuggestionPopUpWindow.getHeight();
}
} else {//calculate x and y for JWindow on any JTextComponent using the carets position
Rectangle rect = null;
try {
rect = textComp.getUI().modelToView(textComp, textComp.getCaret().getDot());//get carets position
} catch (BadLocationException ex) {
ex.printStackTrace();
}
windowX = (int) (rect.getX() + 15);
windowY = (int) (rect.getY() + (rect.getHeight() * 3));
}
//show the pop up
autoSuggestionPopUpWindow.setLocation(windowX, windowY);
autoSuggestionPopUpWindow.setMinimumSize(new Dimension(textComp.getWidth(), 30));
autoSuggestionPopUpWindow.revalidate();
autoSuggestionPopUpWindow.repaint();
}
public void setDictionary(ArrayList<String> words) {
dictionary.clear();
if (words == null) {
return;//so we can call constructor with null value for dictionary without exception thrown
}
for (String word : words) {
dictionary.add(word);
}
}
public JWindow getAutoSuggestionPopUpWindow() {
return autoSuggestionPopUpWindow;
}
public Window getContainer() {
return container;
}
public JTextComponent getTextField() {
return textComp;
}
public void addToDictionary(String word) {
dictionary.add(word);
}
boolean wordTyped(String typedWord) {
if (typedWord.isEmpty()) {
return false;
}
//System.out.println("Typed word: " + typedWord);
boolean suggestionAdded = false;
for (String word : dictionary) {//get words in the dictionary which we added
boolean fullymatches = true;
for (int i = 0; i < typedWord.length(); i++) {//each string in the word
if (!typedWord.toLowerCase().startsWith(String.valueOf(word.toLowerCase().charAt(i)), i)) {//check for match
fullymatches = false;
break;
}
}
if (fullymatches) {
addWordToSuggestions(word);
suggestionAdded = true;
}
}
return suggestionAdded;
}
}
class SuggestionLabel extends JLabel {
private boolean focused = false;
private final JWindow autoSuggestionsPopUpWindow;
private final JTextComponent textComponent;
private final AutoSuggestor autoSuggestor;
private Color suggestionsTextColor, suggestionBorderColor;
public SuggestionLabel(String string, final Color borderColor, Color suggestionsTextColor, AutoSuggestor autoSuggestor) {
super(string);
this.suggestionsTextColor = suggestionsTextColor;
this.autoSuggestor = autoSuggestor;
this.textComponent = autoSuggestor.getTextField();
this.suggestionBorderColor = borderColor;
this.autoSuggestionsPopUpWindow = autoSuggestor.getAutoSuggestionPopUpWindow();
initComponent();
}
private void initComponent() {
setFocusable(true);
setForeground(suggestionsTextColor);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent me) {
super.mouseClicked(me);
replaceWithSuggestedText();
autoSuggestionsPopUpWindow.setVisible(false);
}
});
getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true), "Enter released");
getActionMap().put("Enter released", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
replaceWithSuggestedText();
autoSuggestionsPopUpWindow.setVisible(false);
}
});
}
public void setFocused(boolean focused) {
if (focused) {
setBorder(new LineBorder(suggestionBorderColor));
} else {
setBorder(null);
}
repaint();
this.focused = focused;
}
public boolean isFocused() {
return focused;
}
private void replaceWithSuggestedText() {
String suggestedWord = getText();
String text = textComponent.getText();
String typedWord = autoSuggestor.getCurrentlyTypedWord();
String t = text.substring(0, text.lastIndexOf(typedWord));
String tmp = t + text.substring(text.lastIndexOf(typedWord)).replace(typedWord, suggestedWord);
textComponent.setText(tmp + " ");
}
}
ご覧のとおり、コンストラクターにorなどJTextComponent
ではなくを受け入れるようにコードを変更しました。JTextField
JTextArea
残っている問題は、合格JWindow
に応じて異なる位置にポップアップを表示する必要があることです。つまり、aは下部にオートサジェストウィンドウをポップアップし、/などはカレット/単語の下にポップアップを表示します。JTextComponent
JTextField
JTextArea
JEditorPane
JWindow
クラスshowPopUpWindow()
内のこの特定のメソッドを見てください。AutoSuggestor
private void showPopUpWindow() {
autoSuggestionPopUpWindow.getContentPane().add(suggestionsPanel);
autoSuggestionPopUpWindow.setMinimumSize(new Dimension(textComp.getWidth(), 30));
autoSuggestionPopUpWindow.setSize(tW, tH);
autoSuggestionPopUpWindow.setVisible(true);
int windowX = 0;
int windowY = 0;
if (textComp instanceof JTextField) {//calculate x and y for JWindow at bottom of JTextField
windowX = container.getX() + textComp.getX() + 5;
if (suggestionsPanel.getHeight() > autoSuggestionPopUpWindow.getMinimumSize().height) {
windowY = container.getY() + textComp.getY() + textComp.getHeight() + autoSuggestionPopUpWindow.getMinimumSize().height;
} else {
windowY = container.getY() + textComp.getY() + textComp.getHeight() + autoSuggestionPopUpWindow.getHeight();
}
} else {//calculate x and y for JWindow on any JTextComponent using the carets position
Rectangle rect = null;
try {
rect = textComp.getUI().modelToView(textComp, textComp.getCaret().getDot());//get carets position
} catch (BadLocationException ex) {
ex.printStackTrace();
}
windowX = (int) (rect.getX() + 15);
windowY = (int) (rect.getY() + (rect.getHeight() * 3));
}
//show the pop up
autoSuggestionPopUpWindow.setLocation(windowX, windowY);
autoSuggestionPopUpWindow.setMinimumSize(new Dimension(textComp.getWidth(), 30));
autoSuggestionPopUpWindow.revalidate();
autoSuggestionPopUpWindow.repaint();
}
ご覧のとおり、インスタンスが何であるかを確認し、JTextComponent
それがJTextField
単に(カレットを介して)キャレットの位置を取得しRectangle
、そこから(私の場合はカレットの下に)JTextComponent
位置JWindow
がポップアップするかどうかを確認します。
私は自分の実装を提案することができます。これは、JWindowに表示されるJListに基づいています。このコードをコンボボックスに使用したかったので、keyEvent.consume()呼び出しでUPキーとDOWNキーを無効にしました。
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class GAutoCompletionDecorator {
private final JTextComponent textComponent;
private final JWindow suggestionsPopup;
private final JList completionList;
private final DefaultListModel completionListModel;
public static void decorate(JComboBox comboBox, JFrame parent) {
comboBox.setEditable(true);
final JTextComponent textComponent = (JTextComponent) comboBox.getEditor().getEditorComponent();
decorate(textComponent, parent);
}
private static void decorate(JTextComponent textComponent, JFrame parent) {
final GAutoCompletionDecorator autoCompletionDecorator = new GAutoCompletionDecorator(textComponent, parent);
autoCompletionDecorator.decorate();
}
private GAutoCompletionDecorator(final JTextComponent textComponent, JFrame parent) {
this.textComponent = textComponent;
this.suggestionsPopup = new JWindow(parent);
this.completionListModel = new DefaultListModel();
this.completionList = new JList();
this.completionList.setModel(completionListModel);
this.suggestionsPopup.getContentPane().add(this.completionList);
}
private void decorate() {
textComponent.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent documentEvent) {
updateSuggestions();
}
public void removeUpdate(DocumentEvent documentEvent) {
updateSuggestions();
}
public void changedUpdate(DocumentEvent documentEvent) {
updateSuggestions();
}
});
this.textComponent.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent keyEvent) {
if (keyEvent.getKeyCode() == KeyEvent.VK_DOWN || keyEvent.getKeyCode() == KeyEvent.VK_UP) {
updateSuggestions();
completionList.requestFocus();
completionList.dispatchEvent(keyEvent);
keyEvent.consume();
}
}
public void keyReleased(KeyEvent keyEvent) {
if (keyEvent.getKeyCode() == KeyEvent.VK_DOWN || keyEvent.getKeyCode() == KeyEvent.VK_UP) {
keyEvent.consume();
}
}
});
this.completionList.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent keyEvent) {
if (keyEvent.getKeyCode() == KeyEvent.VK_ESCAPE) {
textComponent.requestFocus();
hideSuggestionsPopup();
} else if (keyEvent.getKeyCode() == KeyEvent.VK_UP) {
if (completionList.getSelectedIndex() == 0) {
completionList.setSelectedIndex(completionListModel.size() - 1);
keyEvent.consume();
}
} else if (keyEvent.getKeyCode() == KeyEvent.VK_DOWN) {
if (completionList.getSelectedIndex() == completionListModel.size() - 1) {
completionList.setSelectedIndex(0);
keyEvent.consume();
}
} else if (keyEvent.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
textComponent.requestFocus();
hideSuggestionsPopup();
textComponent.dispatchEvent(keyEvent);
} else if (keyEvent.getKeyCode() == KeyEvent.VK_ENTER) {
textComponent.requestFocus();
hideSuggestionsPopup();
final String selectedSuggestion = (String) completionList.getSelectedValue();
if (selectedSuggestion != null) {
try {
final int caretPosition = textComponent.getCaretPosition();
textComponent.getDocument().insertString(caretPosition, getCompletionString(selectedSuggestion, textComponent.getText(), caretPosition), null);
} catch (BadLocationException e) {
//ignore
}
}
}
}
});
}
private String getCompletionString(String selectedSuggestion, String text, int caretPosition) {
//we may insert selectedSuggestion fully of some part of it
return selectedSuggestion;
}
private void updateSuggestions() {
final String text = textComponent.getText();
final int caretPosition = textComponent.getCaretPosition();
final List<String> suggestions = getSuggestions(text, caretPosition);
if (suggestions == null || suggestions.size() == 0) {
//hide suggestions window
hideSuggestionsPopup();
} else {
//show suggestions window
showSuggestionsPopup(suggestions);
}
}
private void hideSuggestionsPopup() {
suggestionsPopup.setVisible(false);
}
private void showSuggestionsPopup(List<String> suggestions) {
completionListModel.clear();
for (String suggestion : suggestions) {
completionListModel.addElement(suggestion);
}
final Point textComponentLocation = new Point(textComponent.getLocation());
SwingUtilities.convertPointToScreen(textComponentLocation, textComponent);
Point caretLocation = textComponent.getCaret().getMagicCaretPosition();
if (caretLocation != null) {
caretLocation = new Point(caretLocation);
SwingUtilities.convertPointToScreen(caretLocation, textComponent);
}
suggestionsPopup.pack();
suggestionsPopup.setLocation(caretLocation == null ? textComponentLocation.x : caretLocation.x,
textComponentLocation.y + textComponent.getHeight());
suggestionsPopup.setVisible(true);
}
private List<String> getSuggestions(String text, int caretPosition) {
final List<String> words = new ArrayList<String>();
words.add("suggestion 1");
words.add("suggestion 2");
words.add("suggestion 3");
words.add("suggestion 4");
words.add("suggestion 5");
//make suggestions funny
return text.length() < words.size() ? words.subList(0, words.size() - text.length()) : Collections.<String>emptyList();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JComboBox comboBox = new JComboBox(new String[] {"Choice1", "Choice2"});
comboBox.setEditable(true);
GAutoCompletionDecorator.decorate(comboBox, frame);
frame.add(comboBox);
frame.pack();
frame.setVisible(true);
}
});
}
}