Aquí hay un fragmento para inspirarte. Probablemente necesites reorganizar un poco el código para que sea más fácil de mantener, pero debería darte la esencia.
Básicamente, escuchamos los eventos clave (no me parece relevante escuchar eventos de documentos, por ejemplo, si el usuario pega algo de texto, no quiero que aparezca el panel de sugerencias), y cuando el cursor tiene al menos 2 caracteres detrás, hacemos algunas sugerencias, usando un menú emergente que contiene una lista J de sugerencias (aquí las sugerencias no son realmente significativas, pero no sería demasiado difícil vincular esto a un dictionario). En cuanto a los accesos directos que está mencionando, no debería ser demasiado difícil hacerlo.
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();
}
});
}
}
Buena pregunta, ¿Qué tienes hasta ahora? ¿Estamos usando un diccionario completo de inglés? O un subconjunto? – Coffee
Sin duda no es exactamente lo que está buscando, pero eche un vistazo a la demostración "Autocompletar" de SwingLabs: http://swingx.java.net/ – Rekin
Esta aplicación es un ayudante de mecanografía .. Muestra variantes de caracteres no- presente en el teclado .. EG Presiona A, muestra Â: 1, Á: 2, À: 3 ... 'A' será reemplazado si presiona 1,2 o 3 ... Ya está hecho, pero las sugerencias se muestran en un JLabel en la parte inferior de mi JFrame, porque IDK cómo hacerlo =/ –