This discussion is archived
4 Replies Latest reply: Jan 14, 2011 6:55 AM by 552056 RSS

Swing JList question

552056 Newbie
Currently Being Moderated
I would like a JList to work as follows:


Given the following list

...
GA
HA
IA
ID
IL
IN
KS
KY
LA
...

If my selection is somewhere above HA, and I type "I" I want IA to be selected. If I type "II" I want the second entry beginning with I to be selected, that is ID. If I type "III" I want IL to be selected. And If I type "IL" I want LA to be selected. If "IL" is selected and I type I, I want IN to be selected.

In other words, I want each keystroke to be considered a discrete event which causes selection of the first entry below the current entry beginning with that character and not be aggregated into a String as the normal JList works.

It seems that there must be a timer behind the JList which eventually expires, because if there is enough delay between the keystrokes, the default behavior works as I want. Another way of saying my request would be for that "enough delay" to be 0.

Is there a way to do this without delving deep into the internals
  • 1. Re: Swing JList question
    splungebob Explorer
    Currently Being Moderated
    user549053 wrote:
    I want each keystroke to be considered a discrete event which causes selection of the first entry below the current entry beginning with that character and not be aggregated into a String as the normal JList works.
    Perhaps, I'm not understanding your requirements correctly, but what I think you want works for me out of the box:
    import java.awt.*;
    
    import javax.swing.*;
    
    public class JListDemo implements Runnable
    {
      private static final String ITEMS[] =
      { "GA",  "HA",  "IA",  "ID",  "IL",
        "IN",  "KS",  "KY",  "LA"
      };
      
      private JList jList;
      
      public static void main(String args[])
      {
        SwingUtilities.invokeLater(new JListDemo()); 
      }
      
      public void run()
      {
        jList = new JList(ITEMS);
        jList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        JScrollPane scroll = new JScrollPane(jList);
        scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        
        JFrame f = new JFrame("Items");
        Container contentPane = f.getContentPane();
        contentPane.setLayout(new BorderLayout());
        contentPane.add(scroll, BorderLayout.CENTER);
        
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(180, 220);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
      }
    }
  • 2. Re: Swing JList question
    splungebob Explorer
    Currently Being Moderated
    I was just able to reproduce what you mean by "aggregated into a String". It depends on how fast you type. Given that "IA" is selected, if I type in "IN" fairly quickly (typing speed), then yes, "IN" gets selected.

    However, if I slow down my typing, "ID" will get selected, followed by "LA". Note that merely waiting for "ID" to be selected first wasn't always sufficient enough.

    I'm not sure if there's a way to control/adjust how many millis the UI will wait before discerning between a typed "word" vs. a series of single letters.

    EDIT: It looks like the value you want to adjust is stored in BasicListUI's "timeFactor" variable (default of 1000 millis), and from what I can see, isn't configurable. You'd have to roll your own BasicListUI and set this value to your own needs. See javax.swing.plaf.basic.BasicListUI's inner Handler class for more info.
  • 3. Re: Swing JList question
    camickr Expert
    Currently Being Moderated
    This functionality is contained in the getNextMatch(...) method. Take a look at the source code and then customize it the way you want.
  • 4. Re: Swing JList question
    552056 Newbie
    Currently Being Moderated
    camickr wrote:
    This functionality is contained in the getNextMatch(...) method. Take a look at the source code and then customize it the way you want.
    Thanks. I was misinterpreting the meaning of the start index parameter which is rather confusingly javadoc'ed.

    * @param startIndex the index for starting the search

    I took this to mean the index within the string, but the source code revealed that it referred to the index within the list that searching would start with. Probably pretty obvious but my mind was focused on the string.

    With that understood, the solution was easy:

         public int getNextMatch(String prefix, int startIndex, Position.Bias bias) {
              return super.getNextMatch(prefix.substring(prefix.length() - 1), startIndex, bias);
         }

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points