如何在 JTextArea 摆动中实现自动插入 [英] how would be implements autosugesion in JTextArea swing
问题描述
如果有人回答,请让我回答.基本上需要像谷歌搜索引擎一样,当我们按下任意键时,就会显示与按键相关的建议.
关注萨蒂什·迪曼
来自我的评论/以前的代码 查看此更新:
将 JTextField
与 AutoSuggestor
结合使用:
使用 JTextArea
(或除 JTextField 之外的任何其他 JTextComponent 将导致弹出窗口显示在插入符号下)和 AutoSuggestor
:
import java.awt.Color;导入 java.awt.Dimension;导入 java.awt.GridLayout;导入 java.awt.Rectangle;导入 java.awt.Window;导入 java.awt.event.ActionEvent;导入 java.awt.event.KeyEvent;导入 java.awt.event.MouseAdapter;导入 java.awt.event.MouseEvent;导入 java.util.ArrayList;导入 javax.swing.AbstractAction;导入 javax.swing.JComponent;导入 javax.swing.JEditorPane;导入 javax.swing.JFrame;导入 javax.swing.JLabel;导入 javax.swing.JPanel;导入 javax.swing.JTextArea;导入 javax.swing.JTextField;导入 javax.swing.JWindow;导入 javax.swing.KeyStroke;导入 javax.swing.SwingUtilities;导入 javax.swing.border.LineBorder;导入 javax.swing.event.DocumentEvent;导入 javax.swing.event.DocumentListener;导入 javax.swing.text.BadLocationException;导入 javax.swing.text.JTextComponent;/*** @作者大卫*/公共类测试{公共测试(){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();//为字典创建单词也可以使用 null 作为 AutoSuggestor(..,..,null,..,..,..,..) 的参数,然后在创建 AutoSuggestr insatnce 后调用 AutoSuggestor#setDictionaryArrayListwords = new ArrayList<>();word.add("你好");word.add("遗产");word.add("幸福");word.add("再见");word.add("残忍");word.add("汽车");word.add("战争");word.add("将");word.add("世界");word.add("墙");AutoSuggestor autoSuggestor = new AutoSuggestor(f, frame, words, Color.WHITE.brighter(), Color.BLUE, Color.RED, 0.75f) {@覆盖boolean wordTyped(String typedWord) {System.out.println(typedWord);return super.wordTyped(typedWord);//检查字典中是否匹配,如果找到则返回真或假}};JPanel p = new JPanel();p.add(f);框架.add(p);框架.pack();frame.setVisible(true);}公共静态无效主(字符串 [] args){SwingUtilities.invokeLater(new Runnable() {@覆盖公共无效运行(){新测试();}});}}类 AutoSuggestor {私有最终 JTextComponent textComp;私有最终窗口容器;私人 JPanel 建议面板;私有 JWindow autoSuggestionPopUpWindow;私有字符串 typedWord;私有最终 ArrayList字典 = 新的 ArrayList<>();私人 int currentIndexOfSpace, tW, tH;private DocumentListener documentListener = new DocumentListener() {@覆盖public void insertUpdate(DocumentEvent de) {checkForAndShowSuggestions();}@覆盖public void removeUpdate(DocumentEvent de) {checkForAndShowSuggestions();}@覆盖public void changedUpdate(DocumentEvent de) {checkForAndShowSuggestions();}};私人最终颜色建议TextColor;私人最终颜色建议FocusedColor;public AutoSuggestor(JTextComponent textComp, Window mainWindow, ArrayList words, Color popUpBackground, Color textColor, Color RecommendationFocusedColor, float opacity) {this.textComp = textComp;this.suggestionsTextColor = textColor;this.container = mainWindow;this.suggestionFocusedColor =SuggestedFocusedColor;this.textComp.getDocument().addDocumentListener(documentListener);setDictionary(words);typedWord = "";currentIndexOfSpace = 0;tW = 0;tH = 0;autoSuggestionPopUpWindow = new JWindow(mainWindow);autoSuggestionPopUpWindow.setOpacity(opacity);建议面板 = 新的 JPanel();RecommendationPanel.setLayout(new GridLayout(0, 1));SuggestionsPanel.setBackground(popUpBackground);addKeyBindingToRequestFocusInPopUpWindow();}私有无效 addKeyBindingToRequestFocusInPopUpWindow() {textComp.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "向下释放");textComp.getActionMap().put("向下发布", new AbstractAction() {@覆盖public void actionPerformed(ActionEvent ae) {//聚焦弹出窗口的第一个标签for (int i = 0; i < RecommendationPanel.getComponentCount(); i++) {if (suggestionsPanel.getComponent(i) instanceof SuggestionLabel) {((SuggestionLabel)SuggestionPanel.getComponent(i)).setFocused(true);autoSuggestionPopUpWindow.toFront();autoSuggestionPopUpWindow.requestFocusInWindow();SuggestionsPanel.requestFocusInWindow();SuggestionsPanel.getComponent(i).requestFocusInWindow();休息;}}}});SuggestionsPanel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "向下释放");SuggestionsPanel.getActionMap().put("Downreleased", new AbstractAction() {int lastFocusableIndex = 0;@覆盖public void actionPerformed(ActionEvent ae) {//允许在弹出窗口中滚动标签(我现在知道很hacky :))ArrayListsls = getAddedSuggestionLabels();int max = sls.size();if (max > 1) {//超过 1 个建议for (int i = 0; i < max; i++) {SuggestionLabel sl = sls.get(i);如果(sl.isFocused()){if (lastFocusableIndex == max - 1) {lastFocusableIndex = 0;sl.setFocused(false);autoSuggestionPopUpWindow.setVisible(false);setFocusToTextField();checkForAndShowSuggestions();//触发方法,就好像文档监听器改变发生一样并触发它} 别的 {sl.setFocused(false);lastFocusableIndex = i;}} else if (lastFocusableIndex <= i) {如果(我<最大){sl.setFocused(true);autoSuggestionPopUpWindow.toFront();autoSuggestionPopUpWindow.requestFocusInWindow();SuggestionsPanel.requestFocusInWindow();SuggestionsPanel.getComponent(i).requestFocusInWindow();lastFocusableIndex = i;休息;}}}} else {//只给出了一个建议autoSuggestionPopUpWindow.setVisible(false);setFocusToTextField();checkForAndShowSuggestions();//触发方法,就好像文档监听器改变发生一样并触发它}}});}私有无效 setFocusToTextField() {容器.toFront();container.requestFocusInWindow();textComp.requestFocusInWindow();}公共 ArrayListgetAddedSuggestionLabels() {ArrayListsls = new ArrayList<>();for (int i = 0; i < RecommendationPanel.getComponentCount(); i++) {if (suggestionsPanel.getComponent(i) instanceof SuggestionLabel) {SuggestionLabel sl = (SuggestionLabel)SuggestionPanel.getComponent(i);sls.add(sl);}}返回 sls;}私有无效 checkForAndShowSuggestions() {typedWord = getCurrentlyTypedWord();SuggestionsPanel.removeAll();//删除之前添加的词/jlabels//用于在添加新Jlabels时计算JWindow的大小tW = 0;tH = 0;布尔添加 = wordTyped(typedWord);如果(!添加){如果(autoSuggestionPopUpWindow.isVisible()){autoSuggestionPopUpWindow.setVisible(false);}} 别的 {showPopUpWindow();setFocusToTextField();}}protected void addWordToSuggestions(String word) {SuggestionLabelSuggestionLabel = new SuggestionLabel(word,SuggestionFocusedColor,suggestTextColor,this);计算弹出窗口大小(建议标签);建议面板.添加(建议标签);}public String getCurrentlyTypedWord() {//获取最后一个空格后的最新单词(如果有)或第一个单词(如果没有空格)String text = textComp.getText();字符串 wordBeingTyped = "";text = text.replaceAll("(\r|\n)", " ");如果(文本.包含(")){int tmp = text.lastIndexOf(" ");if (tmp >= currentIndexOfSpace) {currentIndexOfSpace = tmp;wordBeingTyped = text.substring(text.lastIndexOf(" "));}} 别的 {wordBeingTyped = 文本;}返回 wordBeingTyped.trim();}私有无效计算PopUpWindowSize(JLabel标签){//这样我们就可以正确调整JWindow的大小if (tW < label.getPreferredSize().width) {tW = label.getPreferredSize().width;}tH += label.getPreferredSize().height;}私有无效 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) {//为 JTextField 底部的 JWindow 计算 x 和 ywindowX = container.getX() + textComp.getX() + 5;如果 (suggestionsPanel.getHeight() > autoSuggestionPopUpWindow.getMinimumSize().height) {windowY = container.getY() + textComp.getY() + textComp.getHeight() + autoSuggestionPopUpWindow.getMinimumSize().height;} 别的 {windowY = container.getY() + textComp.getY() + textComp.getHeight() + autoSuggestionPopUpWindow.getHeight();}} else {//使用插入符号位置为任何 JTextComponent 上的 JWindow 计算 x 和 y矩形 rect = null;尝试 {rect = textComp.getUI().modelToView(textComp, textComp.getCaret().getDot());//获取脱字符位置} catch (BadLocationException ex) {ex.printStackTrace();}windowX = (int) (rect.getX() + 15);windowY = (int) (rect.getY() + (rect.getHeight() * 3));}//显示弹出窗口autoSuggestionPopUpWindow.setLocation(windowX, windowY);autoSuggestionPopUpWindow.setMinimumSize(new Dimension(textComp.getWidth(), 30));autoSuggestionPopUpWindow.revalidate();autoSuggestionPopUpWindow.repaint();}public void setDictionary(ArrayList words) {字典.清除();如果(单词 == 空){return;//这样我们就可以为字典调用空值的构造函数而不会抛出异常}for(字符串词:词){字典.添加(字);}}公共 JWindow getAutoSuggestionPopUpWindow() {返回 autoSuggestionPopUpWindow;}公共窗口 getContainer() {返回容器;}公共 JTextComponent getTextField() {返回 textComp;}public void addToDictionary(String word) {字典.添加(字);}boolean wordTyped(String typedWord) {if (typedWord.isEmpty()) {返回假;}//System.out.println("Typed word: " + typedWord);布尔建议添加 = 假;for (String word : dictionary) {//获取我们添加的字典中的单词布尔完全匹配 = 真;for (int i = 0; i < typedWord.length(); i++) {//每个字串if (!typedWord.toLowerCase().startsWith(String.valueOf(word.toLowerCase().charAt(i)), i)) {//检查匹配完全匹配 = 假;休息;}}如果(完全匹配){addWordToSuggestions(word);建议添加 = 真;}}退货建议已添加;}}类 SuggestionLabel 扩展 JLabel {私有布尔集中 = false;私人最终 JWindow autoSuggestionsPopUpWindow;私有最终 JTextComponent 文本组件;私人最终 AutoSuggestor autoSuggestor;私人颜色建议TextColor,建议BorderColor;公共建议标签(字符串字符串,最终颜色边框颜色,颜色建议文本颜色,AutoSuggestor autoSuggestor){超级(字符串);this.suggestionsTextColor =SuggestionsTextColor;this.autoSuggestor = autoSuggestor;this.textComponent = autoSuggestor.getTextField();this.suggestionBorderColor = borderColor;this.autoSuggestionsPopUpWindow = autoSuggestor.getAutoSuggestionPopUpWindow();初始化组件();}私有无效initComponent(){setFocusable(true);设置前景(建议文本颜色);addMouseListener(新鼠标适配器(){@覆盖public void mouseClicked(MouseEvent me) {super.mouseClicked(me);replaceWithSuggestedText();autoSuggestionsPopUpWindow.setVisible(false);}});getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true), "输入释放");getActionMap().put("回车释放", new AbstractAction() {@覆盖public void actionPerformed(ActionEvent ae) {replaceWithSuggestedText();autoSuggestionsPopUpWindow.setVisible(false);}});}公共无效setFocused(布尔集中){如果(重点){setBorder(new LineBorder(suggestionBorderColor));} 别的 {设置边界(空);}重绘();this.focused = 专注;}公共布尔 isFocused() {专注回归;}私有无效 replaceWithSuggestedText() {StringSuggestWord = 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,SuggestWord);textComponent.setText(tmp + " ");}}
如您所见,我通过使其构造函数接受 JTextComponent
而不是 JTextField
或 JTextArea
等来更改代码.
我们剩下的问题是我们必须根据传递的 JTextComponent
即一个 JTextField
在不同的位置显示弹出的 JWindow
> 将在底部弹出自动建议窗口,而 JTextArea
/JEditorPane
等将在插入符号/单词下弹出 JWindow
.>
看看AutoSuggestor
类中的这个特定方法showPopUpWindow()
:
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) {//为 JTextField 底部的 JWindow 计算 x 和 ywindowX = container.getX() + textComp.getX() + 5;如果 (suggestionsPanel.getHeight() > autoSuggestionPopUpWindow.getMinimumSize().height) {windowY = container.getY() + textComp.getY() + textComp.getHeight() + autoSuggestionPopUpWindow.getMinimumSize().height;} 别的 {windowY = container.getY() + textComp.getY() + textComp.getHeight() + autoSuggestionPopUpWindow.getHeight();}} else {//使用插入符号位置为任何 JTextComponent 上的 JWindow 计算 x 和 y矩形 rect = null;尝试 {rect = textComp.getUI().modelToView(textComp, textComp.getCaret().getDot());//获取脱字符位置} catch (BadLocationException ex) {ex.printStackTrace();}windowX = (int) (rect.getX() + 15);windowY = (int) (rect.getY() + (rect.getHeight() * 3));}//显示弹出窗口autoSuggestionPopUpWindow.setLocation(windowX, windowY);autoSuggestionPopUpWindow.setMinimumSize(new Dimension(textComp.getWidth(), 30));autoSuggestionPopUpWindow.revalidate();autoSuggestionPopUpWindow.repaint();}
如您所见,我们检查 JTextComponent
是什么实例,如果它不是 JTextField
,只需获取插入符号位置(通过 Rectangle
JTextComponent
和 JWindow
的插入符号的代码> 和位置 JWindow
从那里弹出(在我的例子中插入符号下方).
let me if have you anyone answer, this ans. basically required like as google search engine , when we press any key then it would be display suggestion related pressed key.
regard Satish Dhiman
From my comment/previous code see this update:
Using JTextField
with AutoSuggestor
:
Using JTextArea
(or any other JTextComponent besides JTextField will result in Pop up window being shown under caret) with 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 + " ");
}
}
As you can see I changed the code by making its constructor accept a JTextComponent
rather than a JTextField
or JTextArea
etc.
The problem we are left with is we have to show the pop up JWindow
at a different position depending on the JTextComponent
passed i.e a JTextField
will have autosuggest window pop up at the bottom while JTextArea
/JEditorPane
etc would have the JWindow
pop up under the caret/word.
Have a look at this specific method showPopUpWindow()
in AutoSuggestor
class:
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();
}
As you can see we check to see what instance the JTextComponent
is and if its not a JTextField
simply get the caret position (via the Rectangle
of the caret) of the JTextComponent
and position JWindow
pop up from there (underneath the caret in my case).
这篇关于如何在 JTextArea 摆动中实现自动插入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!