2013/04/15

Add the Function “AutoComplete” in JTextField(2)

In the article Add the Function “AutoComplete” in JTextField,we receive many feedback. One is: “Can you help me, make a search like in facebook? every search there are pictures and text”。 It's not very hard to do this, we can just set the JComboBox's Renderer, By default the Renderer of JComboBox is a JLabel, and the JLabel itself has a function "setIcon", so we can set the Icon to the JLabel, the Code is like this:

cbInput.setRenderer(new DefaultListCellRenderer(){
 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
 super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
 if(value != null){
 this.setText(value.toString());
 String url = value.toString().replaceAll(" ", "_") + ".png";
 ImageIcon icon = getImageIcon(url, IMAGE_ICON_CACHE);
 if(icon != null){
 this.setIcon(icon);
 }
 }
 return this;
 }
 });


In the "getImageIcon" method ,we cache the images, so it no need create a new ImageIcon every time where the UI is Refreshed, which can improve the response time.


public static ImageIcon getImageIcon(String url,Map<String, ImageIcon> IMAGE_ICON_CACHE) {
 if (url == null) {
 return null;
 }
 if (IMAGE_ICON_CACHE.get(url) == null) {
 ImageIcon image = null;
 InputStream in =ResourceAgent.class.getResourceAsStream(url);
 if (in != null) {
 try {
 byte buffer[] = new byte[in.available()];
 for (int i = 0, n = in.available(); i < n; i++) {
 buffer[i] = (byte) in.read();
 }
 Toolkit toolkit = Toolkit.getDefaultToolkit();
 Image img = toolkit.createImage(buffer);
 image = new ImageIcon(img);
 in.close();
 } catch (IOException ex) {
 ex.printStackTrace();
 return null;
 }
 }
 if (image == null) {
 if (ClassLoader.getSystemResource(url) != null) {
 image = new ImageIcon(ClassLoader.getSystemResource(url));
 } else {
 image = new ImageIcon(url);
 }
 }
 if (image == null) {
 System.err.println("can't load image '" + url + "'");
 } else {
 IMAGE_ICON_CACHE.put(url, image);
 }
 }
 return (ImageIcon) IMAGE_ICON_CACHE.get(url);
 }
Finally, it's like this:
The full code file:
package demo; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; import javax.swing.*; import javax.swing.event.*; import demo.images.*; public class Test { public static void main(String[] args) throws Exception { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); JFrame frame = new JFrame(); frame.setTitle("Auto Completion Test"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setBounds(200, 200, 500, 400); ArrayList<String> items = new ArrayList<String>(); // Locale[] locales = Locale.getAvailableLocales(); // for (int i = 0; i < locales.length; i++) { // String item = locales[i].getDisplayName(); // items.add(item); // } items.add("China"); items.add("China Hongkong"); items.add("China Taiwan"); items.add("USA"); items.add("Japan"); JTextField txtInput = new JTextField(); setupAutoComplete(txtInput, items); txtInput.setColumns(30); frame.getContentPane().setLayout(new FlowLayout()); frame.getContentPane().add(txtInput, BorderLayout.NORTH); frame.setVisible(true); } private static boolean isAdjusting(JComboBox cbInput) { if (cbInput.getClientProperty("is_adjusting") instanceof Boolean) { return (Boolean) cbInput.getClientProperty("is_adjusting"); } return false; } private static void setAdjusting(JComboBox cbInput, boolean adjusting) { cbInput.putClientProperty("is_adjusting", adjusting); } public static ImageIcon getImageIcon(String url,Map<String, ImageIcon> IMAGE_ICON_CACHE) { if (url == null) { return null; } if (IMAGE_ICON_CACHE.get(url) == null) { ImageIcon image = null; InputStream in =ResourceAgent.class.getResourceAsStream(url); if (in != null) { try { byte buffer[] = new byte[in.available()]; for (int i = 0, n = in.available(); i < n; i++) { buffer[i] = (byte) in.read(); } Toolkit toolkit = Toolkit.getDefaultToolkit(); Image img = toolkit.createImage(buffer); image = new ImageIcon(img); in.close(); } catch (IOException ex) { ex.printStackTrace(); return null; } } if (image == null) { if (ClassLoader.getSystemResource(url) != null) { image = new ImageIcon(ClassLoader.getSystemResource(url)); } else { image = new ImageIcon(url); } } if (image == null) { System.err.println("can't load image '" + url + "'"); } else { IMAGE_ICON_CACHE.put(url, image); } } return (ImageIcon) IMAGE_ICON_CACHE.get(url); } public static void setupAutoComplete(final JTextField txtInput, final ArrayList<String> items) { final DefaultComboBoxModel model = new DefaultComboBoxModel(); final Map<String,ImageIcon> IMAGE_ICON_CACHE = new HashMap<String, ImageIcon>(); final JComboBox cbInput = new JComboBox(model) { public Dimension getPreferredSize() { return new Dimension(super.getPreferredSize().width, 0); } }; setAdjusting(cbInput, false); for (String item : items) { model.addElement(item); } cbInput.setSelectedItem(null); cbInput.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (!isAdjusting(cbInput)) { if (cbInput.getSelectedItem() != null) { txtInput.setText(cbInput.getSelectedItem().toString()); } } } }); cbInput.setRenderer(new DefaultListCellRenderer(){ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); if(value != null){ this.setText(value.toString()); String url = value.toString().replaceAll(" ", "_") + ".png"; ImageIcon icon = getImageIcon(url, IMAGE_ICON_CACHE); if(icon != null){ this.setIcon(icon); } } return this; } }); txtInput.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { setAdjusting(cbInput, true); if (e.getKeyCode() == KeyEvent.VK_SPACE) { if (cbInput.isPopupVisible()) { e.setKeyCode(KeyEvent.VK_ENTER); } } if (e.getKeyCode() == KeyEvent.VK_ENTER || e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_DOWN) { e.setSource(cbInput); cbInput.dispatchEvent(e); if (e.getKeyCode() == KeyEvent.VK_ENTER) { txtInput.setText(cbInput.getSelectedItem().toString()); cbInput.setPopupVisible(false); } } if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { cbInput.setPopupVisible(false); } setAdjusting(cbInput, false); } }); txtInput.getDocument().addDocumentListener(new DocumentListener() { public void insertUpdate(DocumentEvent e) { updateList(); } public void removeUpdate(DocumentEvent e) { updateList(); } public void changedUpdate(DocumentEvent e) { updateList(); } private void updateList() { setAdjusting(cbInput, true); model.removeAllElements(); String input = txtInput.getText(); if (!input.isEmpty()) { for (String item : items) { if (item.toLowerCase().startsWith(input.toLowerCase())) { model.addElement(item); } } } cbInput.hidePopup(); cbInput.setPopupVisible(model.getSize() > 0); setAdjusting(cbInput, false); } }); txtInput.setLayout(new BorderLayout()); txtInput.add(cbInput, BorderLayout.SOUTH); } }
The ResourceAgent class:

package demo.images;


public class ResourceAgent {
}

and at the some folder, put the icons related to the text show on the list. 



7 comments:

  1. thanks for the reply. .
    I have a problem with "ResourceAgent". .
    on my netbeans, code is not readable / not known
    so that the image does not appear on the list
    Do you have a solution?

    ReplyDelete
    Replies
    1. The ResourceAgent is simple:
      package demo.images;
      public class ResourceAgent {
      }

      and at the some folder, you can put the icons related to the text show on the list.

      Delete
    2. I tried to take a picture from a folder outside the project,
      but that did not work,
      Can you help me?

      Delete
    3. Hi,
      you can use the File and FileInputStream class to read the file from some folder.

      Delete
  2. Can you give me an example. . .?

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. as I can do to make the search not the first letter of the word, an example, I have a list on the basis of users first is their name after their names, and what I want to accomplish is do not look to the first letter of his name but when I go out to put his name options ...

    ReplyDelete