Scrolling a JList to the selected item

You can use the method ensureIndexIsVisible as shown in following example:

import javax.swing.event.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
  
public class Main extends JFrame {
 
   public Main() {
      getContentPane().setLayout(new FlowLayout());
 
      Vector v = new Vector();
      for (int i=0; i<50; i++) {
         v.addElement("Item #" + i);
      }
      final JList list = new JList(v);
 
      final JTextField textfield = new JTextField(5);
      getContentPane().add(new JLabel("Scroll to:"));
      getContentPane().add(textfield);
      JButton button = new JButton("Scroll!");
      getContentPane().add(button);
      button.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            int n = Integer.parseInt(textfield.getText());
            list.ensureIndexIsVisible(n);
         }
      });
      getContentPane().add(new JScrollPane(list));    
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent event) {
            System.exit(0);   
         }      
      });
 
      setSize(200, 230);
   }
   
   public static void main(String[] args) {
      (new Main()).show();
   }
}

Adding a JPanel with a null layout to a JScrollPane

Make sure you set the preferredSize of the JPanel. Invoke the method setViewportView on JScrollPane.

Main.java:

import java.awt.event.*;
import javax.swing.border.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame 
{
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      JPanel panel = createContactPanel();
 
      JScrollPane sp = new JScrollPane();
      sp.setViewportView(panel);
 
      getContentPane().setLayout(new BorderLayout());
      getContentPane().add(sp, BorderLayout.CENTER); 
   }
 
   public JPanel createContactPanel() {
      JLabel titleLbl      = new JLabel("Title");
      JLabel firstNameLbl  = new JLabel("First name");
      JLabel lastNameLbl   = new JLabel("Last name");
      JLabel addressLbl    = new JLabel("Address");
      JLabel cityLbl       = new JLabel("City");
      JLabel zipLbl        = new JLabel("Postal code");
      JLabel countryLbl    = new JLabel("Country");
      JLabel phoneLbl      = new JLabel("Phone number");
      JLabel faxLbl        = new JLabel("Fax number");
      JLabel emailLbl      = new JLabel("E-mail");
      JLabel birthdayLbl   = new JLabel("Birthdate");
      JLabel pickchoiceLbl = new JLabel("Pick a choice");
      JLabel creditCardTypeLbl     = new JLabel("Credit card type");
      JLabel creditCardNumberLbl   = new JLabel("Credit card number");
      JLabel expirationLbl         = new JLabel("Expiration date");
 
      JComboBox titleCombo = new JComboBox(
             new String[] { "-", "Mr", "Mrs", "Miss" });
      JTextField firstNameTf    = new JTextField();
      JTextField lastNameTf     = new JTextField();
      JTextField address1Tf     = new JTextField();
      JTextField address2Tf     = new JTextField();
      JTextField cityTf         = new JTextField();
      JTextField zipTf          = new JTextField();
      JTextField countryTf      = new JTextField();
      JTextField phoneTf        = new JTextField();
      JTextField faxTf          = new JTextField();
      JTextField emailTf        = new JTextField();
      JComboBox bd1Combo = new JComboBox();
      for (int i=1; i<=12; i++) bd1Combo.addItem(""+i);
      JComboBox bd2Combo = new JComboBox();
      for (int i=1; i<=31; i++) bd2Combo.addItem(""+i);
      JComboBox bd3Combo = new JComboBox();
      for (int i=1900; i<2000; i++) bd3Combo.addItem(""+i);
      JComboBox referCombo = new JComboBox();
      referCombo.addItem("Friend");
      referCombo.addItem("Search engine");
      referCombo.addItem("Print Media");
      referCombo.addItem("Banner Add");
      referCombo.addItem("Other");
      JComboBox creditCardTypeCombo = new JComboBox();
      creditCardTypeCombo.addItem("VISA");
      creditCardTypeCombo.addItem("MasterCard");
      creditCardTypeCombo.addItem("American Express");
      JTextField creditCardNumberTf = new JTextField();
      JComboBox expiration1Combo = new JComboBox();
      for (int i=1; i<=12; i++) expiration1Combo.addItem(""+i);
      JComboBox expiration2Combo = new JComboBox();
      for (int i=1; i<=31; i++) expiration2Combo.addItem(""+i);
      JComboBox expiration3Combo = new JComboBox();
      for (int i=1900; i<=2000; i++) expiration3Combo.addItem(""+i);
 
      JPanel panelGeneral = new JPanel();
      panelGeneral.setLayout(null);
      panelGeneral.add(titleLbl);
      panelGeneral.setBorder(new TitledBorder("General Information"));
      titleLbl.setBounds(20, 20, 150, 20);
      panelGeneral.add(firstNameLbl);
      firstNameLbl.setBounds(20, 50, 150, 20);
      panelGeneral.add(lastNameLbl);
      lastNameLbl.setBounds(20, 80, 150, 20);
      panelGeneral.add(addressLbl);
      addressLbl.setBounds(20, 110, 150, 20);
      panelGeneral.add(cityLbl);
      cityLbl.setBounds(20, 170, 150, 20);
      panelGeneral.add(zipLbl);
      zipLbl.setBounds(20, 200, 150, 20);
      panelGeneral.add(countryLbl);
      countryLbl.setBounds(20, 230, 150, 20);
      panelGeneral.add(phoneLbl);
      phoneLbl.setBounds(20, 260, 150, 20);
      panelGeneral.add(faxLbl);
      faxLbl.setBounds(20, 290, 150, 20);
      panelGeneral.add(emailLbl);
      emailLbl.setBounds(20, 320, 150, 20);
      panelGeneral.add(birthdayLbl);
      birthdayLbl.setBounds(20, 350, 150, 20); 
      panelGeneral.add(titleCombo);
      titleCombo.setBounds(150, 20, 60, 20);
      panelGeneral.add(firstNameTf);
      firstNameTf.setBounds(150, 50, 200, 20);
      panelGeneral.add(lastNameTf);
      lastNameTf.setBounds(150, 80, 200, 20);
      panelGeneral.add(address1Tf);
      address1Tf.setBounds(150, 110, 200, 20);  
      panelGeneral.add(address2Tf);
      address2Tf.setBounds(150, 140, 200, 20);  
      panelGeneral.add(cityTf);
      cityTf.setBounds(150, 170, 200, 20);
      panelGeneral.add(zipTf);
      zipTf.setBounds(150, 200, 200, 20);
      panelGeneral.add(countryTf);
      countryTf.setBounds(150, 230, 200, 20);
      panelGeneral.add(phoneTf);
      phoneTf.setBounds(150, 260, 200, 20);
      panelGeneral.add(faxTf);
      faxTf.setBounds(150, 290, 200, 20);
      panelGeneral.add(emailTf);
      emailTf.setBounds(150, 320, 200, 20);
      panelGeneral.add(bd1Combo);
      bd1Combo.setBounds(150, 350, 60, 20);
      panelGeneral.add(bd2Combo);
      bd2Combo.setBounds(220, 350, 60, 20);
      panelGeneral.add(bd3Combo);
      bd3Combo.setBounds(290, 350, 60, 20);
 
      JPanel panelReferral = new JPanel();
      panelReferral.setLayout(null);
      panelReferral.setBorder(new TitledBorder("Where did you hear about us?"));
      panelReferral.add(pickchoiceLbl);
      pickchoiceLbl.setBounds(20, 20, 150, 20);
      panelReferral.add(referCombo);
      referCombo.setBounds(150, 20, 100, 20);
 
      JPanel panelCreditCard = new JPanel();
      panelCreditCard.setLayout(null);
      panelCreditCard.setBorder(new TitledBorder("Payment method"));
      panelCreditCard.add(creditCardTypeLbl);
      creditCardTypeLbl.setBounds(20, 20, 150, 20);
      panelCreditCard.add(creditCardNumberLbl);
      creditCardNumberLbl.setBounds(20, 50, 150, 20);
      panelCreditCard.add(expirationLbl);
      expirationLbl.setBounds(20, 80, 150, 20);
 
      panelCreditCard.add(creditCardTypeCombo);
      creditCardTypeCombo.setBounds(150, 20, 100, 20);
      panelCreditCard.add(creditCardNumberTf);
      creditCardNumberTf.setBounds(150, 50, 150, 20);
      panelCreditCard.add(expiration2Combo);
      expiration2Combo.setBounds(220, 80, 60, 20);
      panelCreditCard.add(expiration3Combo);
      expiration3Combo.setBounds(290, 80, 60, 20);
 
      JPanel panel = new JPanel();
      panel.setLayout(null);
      panel.add(panelGeneral);
      panelGeneral.setBounds(10, 20, 370, 400);
      panel.add(panelReferral);
      panelReferral.setBounds(10, 430, 370, 50);
      panel.add(panelCreditCard);
      panelCreditCard.setBounds(10, 490, 370, 120);
      
      panel.setPreferredSize(new Dimension(380, 620)); 
 
      return panel;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}

Creating a JTextField as an element of JList

This example uses an EditableJList, a custom JList that only allows an EditableJList.EditableListModel as model. Our EditableListModel can only contain JTextComponents (JTextField, JTextArea, …) items.
The behavior is such that when double-clicking on the JList, the selected item is detected using the method locationToIndex and a border is added to it. The border will be removed when the textfield looses focus. To ensure that the JList element is being updated while editing the textfield, every DocumentEvent is captured and fireContentsChanged is called.
Main.java:

import javax.swing.event.*;
import javax.swing.text.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
  
public class Main extends JFrame {
 
   public Main() {
      getContentPane().setLayout(new BorderLayout());
 
      EditableJList.EditableListModel listModel = new EditableJList.EditableListModel();
 
      // populate listmodel
      Random r = new Random();
      for (int i=0; i&lt;50; i++) {
         String item = &quot;list item # &quot; + (Math.abs(r.nextInt()) % 100);
         JTextField tc = new JTextField(item);
//         JTextArea tc = new JTextArea(item);
//         JEditorPane tc = new JEditorPane(&quot;text/html&quot;, &quot;&lt;h3&gt;&quot; + item + &quot;&lt;/h3&gt;&quot;);
         listModel.addElement(tc);
      }
 
      EditableJList list = new EditableJList(listModel); 
      getContentPane().add(BorderLayout.CENTER, new JScrollPane(list));    
  
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent event) {
            System.exit(0);   
         }      
      });
 
      pack();
   }
 
   public static void main(String[] args) {
      (new Main()).show();
   }
}
 
class EditableJList extends JList {
   public EditableJList(EditableListModel listModel) {
      setModel(listModel);
      addMouseListener();
 
      // set our custom cell renderer
      setCellRenderer(new TextComponentCellRenderer()); 
   }
 
   private void addMouseListener() {  
      MouseListener mouseListener = new MouseAdapter() {
         public void mouseClicked(MouseEvent e) {
            if (e.getClickCount() == 2) {
               EditableListModel listModel = (EditableListModel) getModel();
 
               // determine the clicked item
               int index = locationToIndex(e.getPoint());
               Object value = listModel.getElementAt(index);
               final JTextComponent tc = (JTextComponent) value;
 
               // set the appropriate border for editing 
               String classname = tc.getClass().getName().toString();
               classname = classname.substring(classname.lastIndexOf(&quot;.&quot;));
               tc.setBorder(UIManager.getBorder(classname + &quot;border&quot;));
 
               // make this border appear in the JList
               listModel.updateItem(index);
 
               tc.addFocusListener(new FocusListener() {
                  public void focusGained(FocusEvent fe) {
                     // no selection color desired when editing a JTextComponent
                     clearSelection();
                  }
 
                  public void focusLost(FocusEvent fe) {
                     // remove the border again when stopped editing
                     tc.setBorder(null);
                  }
               });
 
               // request the focus on this component to be able to edit it
               tc.requestFocus();
 
               // listen to all key events on the JTextComponent and update the 
               // JList item every time.  Without this, you won't see the changes.           
               tc.getDocument().addDocumentListener(new UpdateListDocumentListener(listModel, index));
            }
         }
      };
 
      addMouseListener(mouseListener);
   }
 
   // DocumentListener that takes care of updating a JList item
   // when editing it.  Calls updateItem on our custom EditableListModel
   private class UpdateListDocumentListener implements DocumentListener {
      private EditableListModel elm;
      private int index;
 
      public UpdateListDocumentListener(EditableListModel elm, int index) {
         this.elm = elm;
         this.index = index;
      }
 
      public void insertUpdate(DocumentEvent e) {
         elm.updateItem(index);
      }
 
      public void removeUpdate(DocumentEvent e) {
         elm.updateItem(index);
      }
 
      public void changedUpdate(DocumentEvent e) {
         elm.updateItem(index);
      }
   }
 
   private class TextComponentCellRenderer implements ListCellRenderer {
      public Component getListCellRendererComponent(
         JList list,
         Object value,            // value to display
         int index,               // cell index
         boolean isSelected,      // is the cell selected
         boolean cellHasFocus)    // the list and the cell have the focus
      {
         JTextComponent tc = (JTextComponent) value;
         if (isSelected) {
            tc.setBackground(list.getSelectionBackground());
            tc.setForeground(list.getSelectionForeground());
         }
         else {
            tc.setBackground(list.getBackground());
            tc.setForeground(list.getForeground());
         }
 
         tc.setEnabled(list.isEnabled());
         tc.setFont(list.getFont());
         tc.setBorder(null);
 
         return (Component) value;
      }
   }
 
   public static class EditableListModel extends DefaultListModel {
      public void updateItem(int index) {
         fireContentsChanged(this, index, index);
      }

      public void addElement(JTextComponent tc) {
         super.addElement(tc);
      }
   }
}

Making the scrolling in JScrollPane faster

A new feature has been implemented in Swing 1.1.1 that makes scrolling faster in most cases. The idea is to only update the exposed viewport (the visible region) when scrolling. To enable this, set the property EnableWindowBlit to true.

   scrollpane.getViewport().putClientProperty("EnableWindowBlit", Boolean.TRUE);

Setting the background color of a JTable inside a JScrollPane

Try the following (JDK1.3+):

   scrollPane.getViewport().setBackground(table.getBackground());

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame 
{
   public Main() {
      super(&quot;Table example, Wines from Bordeaux&quot;);
 
      Object[][] tabledata = {
            { &quot;Chateau Meyney, St. Estephe&quot;, 	   new Integer(1994), &quot;$18.75&quot;},
            { &quot;Chateau Montrose, St. Estephe&quot;, 	   new Integer(1975), &quot;$54.25&quot; },
            { &quot;Chateau Gloria, St. Julien&quot;, 	   new Integer(1993), &quot;$22.99&quot; },
            { &quot;Chateau Beychevelle, St. Julien&quot;,   new Integer(1970), &quot;$61.63&quot; },
            { &quot;Chateau La Tour de Mons, Margeaux&quot;, new Integer(1975), &quot;$57.03&quot; },
            { &quot;Chateau Brane-Cantenac, Margeaux&quot;,  new Integer(1978), &quot;$49.92&quot; },
      };
 
      String columnheaders[] = { &quot;Wine&quot;, &quot;Vintage&quot;, &quot;Price&quot; };
 
      JTable table = new JTable(tabledata, columnheaders);
      table.setPreferredScrollableViewportSize(new Dimension(500, 70));
 
      table.setBackground(Color.red);
  
      JScrollPane scrollPane = new JScrollPane(table);
      scrollPane.getViewport().setBackground(table.getBackground());
 
      getContentPane().setLayout(new BorderLayout());
      getContentPane().add(BorderLayout.CENTER, scrollPane);
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(550, 300);
      main.setVisible(true);
   }
}

Detecting JScrollPane events

Add a AdjustmentListener to the horizontal or vertical scrollbar of the JScrollPane (you can get its reference with the methods getHorizontalScrollBar and getVerticalScrollBar).

Note that the AdjustmentType will always be AdjustmentEvent.TRACK.
(From the API: “Note that the AdjustmentEvents type property will always have a placeholder value of AdjustmentEvent.TRACK because all changes to a BoundedRangeModels value are considered equivalent. To change the value of a BoundedRangeModel one just sets its value property, i.e. model.setValue(123). No information about the origin of the change, e.g. it’s a block decrement, is provided. We don’t try fabricate the origin of the change here.”)

Main.java:

import javax.swing.table.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame
{
   public Main() throws Exception {
      getContentPane().setLayout(new BorderLayout());
 
      JPanel panel = createPanel();
 
      JScrollPane scrollpane = new JScrollPane(panel);
      JScrollBar scrollbar = scrollpane.getVerticalScrollBar();
      scrollbar.addAdjustmentListener(new AdjustmentListener() {
         public void adjustmentValueChanged(AdjustmentEvent ae) {
            System.out.println(translateAdjustmentEvent(ae));
         }
      });
 
      getContentPane().add(BorderLayout.CENTER, scrollpane);
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public String translateAdjustmentEvent(AdjustmentEvent ae) {
      String s = "type = ";
      switch(ae.getAdjustmentType()) {
         case AdjustmentEvent.UNIT_INCREMENT:
            s += "UNIT_INCREMENT"; break;
         case AdjustmentEvent.UNIT_DECREMENT:
            s += "UNIT_DECREMENT"; break;
         case AdjustmentEvent.BLOCK_INCREMENT:
            s += "BLOCK_INCREMENT"; break;
         case AdjustmentEvent.BLOCK_DECREMENT:
            s += "BLOCK_DECREMENT"; break;
         case AdjustmentEvent.TRACK:
            s += "TRACK"; break;
         default: break;
      }
      s += ", current value = " + ae.getValue();
 
      return s;
   }
 
   public static JPanel createPanel() throws Exception {
      JPanel panel = new JPanel();
      panel.setLayout(new GridLayout(50, 20, 10, 10));
 
      for (int i=0; i<50; i++) {
         for (int j=0; j<20; j++) {
            JLabel label = new JLabel("label " + i + ", " + j);
            panel.add(label);    
         }
      }
 
      return panel;
   }
 
   public static void main(String [] args) throws Exception  {
      Main main = new Main();
      main.setSize(600, 600);
      main.setVisible(true);
   } 
} 

Incorporating speech in a Swing application

1) First you need to download a speech engine. For example, you can download for free the Microsoft’s Speech SDK here. (Beware: version 5.1 is 68MB). Use the tools available to make sure the SDK is properly installed and trained to your voice.

2) Then get an implementation of Sun’s Java Speech API (JSAPI). The one I used in this example is from the CloudGarden. Follow the instructions on this page to find out how to install: copy the files jsapi.dll and jsapi.jar to JRE_HOME/lib/ext and adjust your classpath so that it includes jsapi.jar, necessary to compile following sample program.

3) This sample program was written by looking at the Cloud Garden examples. I dictated the following text to the app: “Last night, after a productive day of work, I joined my girlfriend in bed and quoted a very famous poet, who’s name escapes me. I said: ‘I feel great sexual desire for you right now.’. She said she’s not into poetry.”. The result (see window) was better than I expected.

Main.java:

import javax.speech.recognition.*;
import javax.speech.synthesis.*;
import javax.speech.*;
 
import javax.swing.text.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame
{ 
   TextComponentSpeechEnabler tcse;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            tcse.deallocate();
            System.exit(1);
         }
      });
 
      getContentPane().setLayout(new BorderLayout(10, 10));
      JTextArea textArea = new JTextArea();
      textArea.setLineWrap(true);
 
      try {
         tcse = new TextComponentSpeechEnabler(textArea);
         getContentPane().add(BorderLayout.CENTER, tcse.getPanel());
      }
      catch(Exception e) {
         e.printStackTrace();
      }
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(500, 500);
      main.setVisible(true);
   }
}
 
class TextComponentSpeechEnabler
{
   static Recognizer recognizer;
 
   JPanel         textComponentPanel;
   JTextComponent textComponent;
   JTextField     speakerName;
   JTextArea      statusArea;
 
   public TextComponentSpeechEnabler(JTextComponent textComponent) throws Exception {
      this.textComponent = textComponent;
      
      createPanel();
      initializeRecognizer();
   }
  
   public void initializeRecognizer() throws Exception {
      recognizer = Central.createRecognizer(null);
      recognizer.addResultListener(new MyResultListener());
      recognizer.allocate();
      recognizer.waitEngineState(Recognizer.ALLOCATED);
 
      SpeakerManager speakerManager = recognizer.getSpeakerManager();
      SpeakerProfile[] speakers = speakerManager.listKnownSpeakers();
      for (int i=0; i<speakers.length; i++) {
         addStatusText("Found profile of " + speakers[i].getName());
      }
 
      addStatusText("Current profile is " +
                                   speakerManager.getCurrentSpeaker().getName());
      speakerName.setText(speakerManager.getCurrentSpeaker().getName());
      speakerManager.setCurrentSpeaker(speakers[0]);
 
      DictationGrammar dictation = recognizer.getDictationGrammar("dictation");
      dictation.setEnabled(true);
 
      recognizer.commitChanges();
 
      recognizer.requestFocus();
      recognizer.resume(); 
   }
 
   public void deallocate() {
      System.out.println("deallocated!");
      try {
         recognizer.deallocate();
      }
      catch(Exception e) {
         e.printStackTrace();
      }
   }
 
   private void createPanel() {
      textComponentPanel = new JPanel(new BorderLayout(10, 10));
      JPanel northPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
      northPanel.add(new JLabel("Speaker name:  "));
      speakerName = new JTextField(25);
      northPanel.add(speakerName);
      textComponentPanel.add(BorderLayout.NORTH, northPanel);
      textComponentPanel.add(BorderLayout.CENTER, new JScrollPane(textComponent));
 
      statusArea = new JTextArea(10, 50);
      textComponentPanel.add(BorderLayout.SOUTH, new JScrollPane(statusArea));   
   }
  
   public JPanel getPanel() {
      return textComponentPanel;
   }
 
   public void addStatusText(final String s) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            statusArea.append(s + "n");
            statusArea.setCaretPosition(statusArea.getDocument().getLength());
         }
      });
   }
 
   public void addText(final String s) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            textComponent.setText(textComponent.getText() + s);
            textComponent.setCaretPosition(textComponent.getDocument().getLength());
         }
      });
   }
  
   class MyResultListener extends ResultAdapter {
      public void resultRejected(ResultEvent e) {
      }
 
      public void resultCreated(ResultEvent e) {
      }
 
      public void resultUpdated(ResultEvent e) {
      }
 
      public void resultAccepted(ResultEvent e) {
         FinalResult finalResult = (FinalResult)(e.getSource());
         ResultToken tokens[] = null;
         tokens = finalResult.getBestTokens();
 
         StringBuffer sb = new StringBuffer();
         for (int i=0; i<tokens.length; i++) {
            sb.append(tokens[i].getSpokenText() + " ");  
         }
         addText(sb.toString());
         addStatusText("" + finalResult);
      }
   }
}

Feel free to mail me any improvements!

Scrolling a JScrollPane to the bottom programmatically

Call the method scrollRectToVisible of the component that is added to the JScrollPane container as shown in following example:

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame
{
   public Main() throws Exception {
      getContentPane().setLayout(new BorderLayout());
 
      final JPanel panel = createPanel(); 
      final JScrollPane scrollpane = new JScrollPane(panel);
 
      JButton button = new JButton("Scroll to bottom!");
      button.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            panel.scrollRectToVisible(
              new Rectangle(0, panel.getHeight()-1, 1, 1));
         }
      });
 
      getContentPane().add(BorderLayout.NORTH, button);
      getContentPane().add(BorderLayout.CENTER, scrollpane);
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public static JPanel createPanel() throws Exception {
      JPanel panel = new JPanel();
      panel.setLayout(new GridLayout(50, 20, 10, 10));
 
      for (int i=0; i<50; i++) {
         for (int j=0; j<20; j++) {
            JLabel label = new JLabel("label " + i + ", " + j);
            panel.add(label);    
         }
      }
 
      return panel;
   }
 
   public static void main(String [] args) throws Exception  {
      Main main = new Main();
      main.setSize(600, 600);
      main.setVisible(true);
   } 
} 

Have two JTrees vertically aligned in a JScrollPane

Main.java:

import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
import java.awt.*;
import java.net.*;
import java.awt.event.*;
 
public class Main extends JFrame
{
   public Main() {
      DefaultMutableTreeNode root = createNodes();
      JTree tree1 = new JTree(root);
      JTree tree2 = new JTree(root);
 
      tree1.addTreeSelectionListener(new TreeSelectionListener() {
         public void valueChanged(TreeSelectionEvent e) {         
            TreePath path = e.getPath();
            System.out.println(path.getLastPathComponent());     
         }
      });
 
      tree2.addTreeSelectionListener(new TreeSelectionListener() {
         public void valueChanged(TreeSelectionEvent e) {         
            TreePath path = e.getPath();
            System.out.println(path.getLastPathComponent());     
         }
      });
  
      Box box = Box.createVerticalBox();
      box.add(tree1);
      box.add(tree2);
 
      // bugparade #4833645
      tree1.setMinimumSize(tree1.getPreferredSize());
      tree1.setAlignmentX(0);
      tree2.setMinimumSize(tree2.getPreferredSize());
      tree2.setAlignmentX(0);
 
      getContentPane().setLayout(new BorderLayout());
     
      JScrollPane sp = new JScrollPane(box);
      sp.getViewport().setBackground(Color.white);
 
      getContentPane().add(BorderLayout.NORTH, sp);
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
  
   public static DefaultMutableTreeNode createNodes() {
      DefaultMutableTreeNode root = new DefaultMutableTreeNode("Java");
      
      DefaultMutableTreeNode j2se = new DefaultMutableTreeNode("J2SE");
      DefaultMutableTreeNode j2ee = new DefaultMutableTreeNode("J2EE");
      DefaultMutableTreeNode j2me = new DefaultMutableTreeNode("J2ME");
 
      j2se.add(new DefaultMutableTreeNode("http://java.sun.com/j2se/"));
      j2ee.add(new DefaultMutableTreeNode("http://java.sun.com/j2ee/"));
      j2me.add(new DefaultMutableTreeNode("http://java.sun.com/j2me/"));
 
      root.add(j2se);
      root.add(j2ee);
      root.add(j2me);
 
      return root;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}

Force the JScrollPane to scroll to the next JTextField when I press the TAB-Key

There are three steps to this:

1. Listen for focus events coming from the components that you want to scroll to. (This works for most component classes, not just JTextField.)

2. In the event listener, find the location of the component that now has focus with getBounds().

3. Ask the scrolled component to make that location visible with scrollRectToVisible(). NOTE! The obvious thing to call scrollRectToVisible on is the JScrollPane, which will compile fine but won’t do what you want. You must call scrollRectToVisible on the object contained in viewport of the scrollpane.

This Forte-generated example shows how this works for a simple panel containing a number of JTextFields. Notice that scrollRectToVisible is called on the JPanel containing the text fields.

TestFocus.java:

public class TestFocus extends javax.swing.JFrame {
 
    /** Creates new form TestFocus */
    public TestFocus() {
        initComponents();
    }
 
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents() {
        scrollPane = new javax.swing.JScrollPane();
        panel = new javax.swing.JPanel();
        jTextField1 = new javax.swing.JTextField();
        jTextField2 = new javax.swing.JTextField();
        jTextField3 = new javax.swing.JTextField();
        jTextField4 = new javax.swing.JTextField();
         
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                exitForm(evt);
            }
        });
        
        scrollPane.setPreferredSize(new java.awt.Dimension(120, 80));
        panel.setLayout(new java.awt.GridLayout(0, 1, 0, 15));
        
        jTextField1.setFont(new java.awt.Font("Dialog", 0, 18));
        jTextField1.setText("jTextField1");
        jTextField1.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                jTextFieldFocusGained(evt);
            }
        });
         
        panel.add(jTextField1);
        
        jTextField2.setFont(new java.awt.Font("Dialog", 0, 18));
        jTextField2.setText("jTextField2");
        jTextField2.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                jTextFieldFocusGained(evt);
            }
        });
        
        panel.add(jTextField2);
        
        jTextField3.setFont(new java.awt.Font("Dialog", 0, 18));
        jTextField3.setText("jTextField3");
        jTextField3.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                jTextFieldFocusGained(evt);
            }
        });
        
        panel.add(jTextField3);
        
        jTextField4.setFont(new java.awt.Font("Dialog", 0, 18));
        jTextField4.setText("jTextField4");
        jTextField4.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                jTextFieldFocusGained(evt);
            }
        });
        
        panel.add(jTextField4);
        
        scrollPane.setViewportView(panel);
        
        getContentPane().add(scrollPane, java.awt.BorderLayout.CENTER);
        
        pack();
    }
 
    private void jTextFieldFocusGained(java.awt.event.FocusEvent evt) {
        java.awt.Component focusedComponent = evt.getComponent();
        panel.scrollRectToVisible(focusedComponent.getBounds(null));
        repaint();
    }
 
    /** Exit the Application */
    private void exitForm(java.awt.event.WindowEvent evt) {
        System.exit(0);
    }
 
    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        new TestFocus().show();
    }
 
    // Variables declaration - do not modify
    private javax.swing.JScrollPane scrollPane;
    private javax.swing.JPanel panel;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JTextField jTextField2;
    private javax.swing.JTextField jTextField3;
    private javax.swing.JTextField jTextField4;
    // End of variables declaration

}

If your panel of components contains a JTextArea, or another JTextComponent subclass, then be aware that those components will absorb TABs into themselves instead of allowing the TAB to change focus. You can disable this behavior by creating a subclass that overrides isManagingFocus() to always return false.