среда, 25 декабря 2013 г.

Случайно стал модератором сайта по VBA
http://www.quizful.net/test/vba-excel

Вот так вот. 

среда, 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, пока тот не закрыли. Попробуем теперь кое-что еще...   

вторник, 16 октября 2012 г.

Опять про Google Play....


Накапало уже на Google Play порядка 10 баксов. Правда приложения простенькие. Порядка 10 шт. Одно скоро наберет 1000 бесплатных скачиваний уже.

Открыл для себя knowledgeblackbelt.com. И уже заработал на оранжевый пояс. Скоро получу зеленый - 2 балла всего осталось. Надо Swing повторить.

суббота, 7 апреля 2012 г.

О хорошем в разработке приложений 


Приятно, что твое приложение интересно людям из стольких стран. Однако пора думать о монетизации. Продажи пока на нуле. Скачивают бесплатные версии