среда, 25 декабря 2013 г.
среда, 16 октября 2013 г.
Поле с автозаполнением на основе JTextArea
Люблю Java за то, что на ней приятно логику писать. Просто нереально приятно!
Но когда дело доходит то графики - все немного усложняется. Многих Java из-за этого отпугивает. Пока "врубишься" во все тонкости принципа "написал раз - работает везде" применительно к интерфейсу, особенно применительно к Swing, вспотеешь...
Делаю приложение, соединяющееся с БД через SQL (толстого клиента, без Web). Пользователь должен заполнять поля формы, список значений в которых ограничен списком из БД. И нет в стандартной библиотеке готового компонента (JComboBox, JList, JTextField или JTextArea), который бы автоматически заполнялся (или фильтровал список выбора) при вводе данных с клавиатуры (список очень большой - без этого никак). Вроде есть на сайтах информация как это сделать - но не сразу въедешь.
Поэтому кидаю для всех желающих готовый компонент. Он расширяет JTextArea.
Сразу напишу - что за основу брал уже написанный кем-то в сети код - но он не совсем корректно работал в некоторых ситуациях. Пришлось допиливать (оригинал тут ).
А теперь собственно код:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
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.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.BorderFactory;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
public class JTextAreaAutocompleted extends JTextArea{
private List<String> dataList;
private SuggestionPanel suggestion;
private JTextArea textarea;
public JTextAreaAutocompleted(List<String> dataList,String startValue) {
super(24, 80);
this.setText(startValue);
this.dataList=dataList;
textarea=this;
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 (textarea.getText().length()==1){
textarea.setText("");
e.consume();
showSuggestionLater();
}
if (suggestion != null) {
if (suggestion.insertSelection()) {
e.consume();
}
}
}
}
@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 (e.getKeyCode() == KeyEvent.VK_ENTER){
hideSuggestion();
}
}
@Override
public void keyPressed(KeyEvent e) {
}
});
}
class SuggestionPanel {
private JList list;
private JPopupMenu popupMenu;
public SuggestionPanel(JTextArea textarea, int position, String subWord, Point location) {
list = createSuggestionList(position, subWord);
popupMenu = new JPopupMenu();
popupMenu.removeAll();
popupMenu.setOpaque(false);
popupMenu.setBorder(null);
JScrollPane jpPM=new JScrollPane(list);
jpPM.setPreferredSize(new Dimension(600,500));
popupMenu.add(jpPM, BorderLayout.CENTER);
if (list.getModel().getSize()==0){
} else{
popupMenu.show(textarea, location.x+30, textarea.getBaseline(0, 0) + location.y);
}
}
public void hide() {
popupMenu.setVisible(false);
suggestion = null;
}
private List<String> getFiltredList(final String subWord){
List<String> listFiltered=new ArrayList<String>();
for (String s: dataList){
String subWordCorrect=subWord;
Pattern p=Pattern.compile("^"+subWordCorrect+".*", Pattern.CASE_INSENSITIVE+Pattern.UNICODE_CASE);
Matcher m = p.matcher(s);
if (m.matches()){
listFiltered.add(s);
}
}
return listFiltered;
}
private JList createSuggestionList(final int position, final String subWord) {
List<String> listFiltered=getFiltredList(subWord);
Object[] data = listFiltered.toArray();//new Object[10];
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();
suggestion.hide();
}
}
});
return list;
}
public boolean insertSelection() {
if (list.getSelectedValue() != null) {
final String selectedSuggestion = ((String) list.getSelectedValue());
textarea.setText(selectedSuggestion);
return true;
}
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);
};
});
}
}
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) {
start--;
}
if (start > position) {
return;
}
String subWord = text.substring(start, position);
if (subWord.length() < 1) {
//Test.w();
suggestion = new SuggestionPanel(textarea, position, subWord, location);
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();
}
}
}
Вам осталось только заменить функцию getFiltredList на возвращение своего списка значений.
Если пригодилось - сообщайте. Комментируйте, если найдете ошибки!
четверг, 21 марта 2013 г.
О результатах размещения приложений на Google Play...
Короче говоря, результат по нулям. Платных скачивается дай бог 4 шт/мес (все по 1 баксу), бесплатных скачивается значительно больше (на некоторых моих приложениях на Google Play - уже более 1500 скачиваний). Мало скачиваний потому, что это так называемые quiz.
Но зато круто стал программировать в java. Получил синий пояс на knowledgeblackbelt.com, пока тот не закрыли. Попробуем теперь кое-что еще...
Подписаться на:
Комментарии (Atom)

