Creating a JList with icons and text

Main.java:

import java.awt.image.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
  
public class Main 
{
   public static void main(String args[]) {
      JFrame frame = new JFrame("JList ImageIcon Demonstration");
 
      DefaultListModel dlm = new DefaultListModel();
      dlm.addElement(new ListEntry("Audio", new ImageIcon("audio.gif")));
      dlm.addElement(new ListEntry("Control Panel", new ImageIcon("controlpanel.gif")));
      dlm.addElement(new ListEntry("Folder", new ImageIcon("folder.gif")));
      dlm.addElement(new ListEntry("Local Disk (C:)", new ImageIcon("mycomp.gif")));
      dlm.addElement(new ListEntry("doc on '192.168.0.1' (Z:)", new ImageIcon("network.gif")));
 
      JList list = new JList(dlm);
      list.setCellRenderer(new ListEntryCellRenderer());
         
      frame.getContentPane().add(BorderLayout.CENTER, new JScrollPane(list)); 
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setVisible(true);
   }
}
 
class ListEntry 
{
   private String value;
   private ImageIcon icon;
 
   public ListEntry(String value, ImageIcon icon) {
      this.value = value;
      this.icon = icon;
   }
 
   public String getValue() {
      return value;
   }
 
   public ImageIcon getIcon() {
      return icon;
   }
 
   public String toString() {
      return value;
   }
}
 
class ListEntryCellRenderer
 extends JLabel implements ListCellRenderer
{
   private JLabel label;
 
   public Component getListCellRendererComponent(JList list, Object value,
                                                 int index, boolean isSelected,
                                                 boolean cellHasFocus) {
      ListEntry entry = (ListEntry) value;
 
      setText(value.toString());
      setIcon(entry.getIcon());
  
      if (isSelected) {
         setBackground(list.getSelectionBackground());
         setForeground(list.getSelectionForeground());
      }
      else {
         setBackground(list.getBackground());
         setForeground(list.getForeground());
      } 
 
      setEnabled(list.isEnabled());
      setFont(list.getFont());
      setOpaque(true);
 
      return this;
   }
}

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);
   }
}

Setting the top-left icon of a JInternalFrame

Use setFrameIcon():

JInternalFrame frame = new JInternalFrame("Test",false,false,false,false);

try {
  URL url = new URL("http://localhost/images/icon.gif");
  ImageIcon icon = new ImageIcon(url);
  frame.setFrameIcon(icon);
} catch (MalformedURLException me) {}

...

Detecting a selection change on a JComboBox

Use an ActionListener.

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
 
public class Main extends JFrame { 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      }); 
 
      Vector v = new Vector();
      v.add(&quot;first element&quot;);
      v.add(&quot;second element&quot;);
      v.add(&quot;third element&quot;);
      v.add(&quot;fourth element&quot;);
      v.add(&quot;fifth element&quot;);
 
      final JComboBox cb = new JComboBox(v);
      cb.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            System.out.println(cb.getSelectedItem());
         }
      });
      getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
      getContentPane().add(new JLabel(&quot;Select element:&quot;));
      getContentPane().add(cb);
   } 
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
      main.setSize(300, 150);
   }
}

Creating a sorted JList

This example shows you a method sortList that gets the JList data, puts them in an array, sorts them using Arrays.sort and updates the list model:

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 BorderLayout());
 
      final DefaultListModel listModel = new DefaultListModel();   
 
      // populate listmodel
      Random r = new Random();
      for (int i=0; i<50; i++) {
         listModel.addElement("list item # " + (Math.abs(r.nextInt()) % 100));
      }
 
      final JList list = new JList(listModel); 
 
      getContentPane().add(BorderLayout.CENTER, new JScrollPane(list));    
      JButton sortButton = new JButton("Sort");
      sortButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            sortList(list);
         }
      });
      getContentPane().add(BorderLayout.SOUTH, sortButton);
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent event) {
            System.exit(0);   
         }      
      });
 
      pack();
   }
 
   public void sortList(JList list) {
      ListModel model = list.getModel();
 
      int n = model.getSize();
      String[] data = new String[n]; 
 
      for (int i=0; i<n; i++) { 
         data[i] = (String) model.getElementAt(i); 
      }
 
      Arrays.sort(data); 
 
      list.setListData(data); 
   }
   
   public static void main(String[] args) {
      (new Main()).show();
   }
}

Creating a JMenuItem with an image

Two constructors of JMenuItem take an Icon as parameters. Try the following example with these animated! GIFs:

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
   
public class Main extends JFrame {
   public Main() {
      getContentPane().setLayout(new FlowLayout());
 
      JMenuBar menuBar = new JMenuBar();
      JMenu menu = new JMenu("menu");
      JMenuItem menuItem1 = new JMenuItem("male", new ImageIcon("male.gif"));
      JMenuItem menuItem2 = new JMenuItem("female", new ImageIcon("female.gif"));
      menu.add(menuItem1);
      menu.add(menuItem2);
      menuBar.add(menu);
 
      this.setJMenuBar(menuBar); 
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent event) {
            System.exit(0);   
         }      
      });
 
      setSize(400, 400);
   }
 
   public static void main(String[] args) {
      (new Main()).show();
   }
}

Changing the orientation of a JTextField, eg. right to left

You can use the method setComponentOrientation defined in the Component class, so
you can invoke it on most Swing components.
It does not seem to work properly using JDK1.2, but does with JDK1.3.

import javax.swing.event.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
   
public class Main extends JFrame
{
   public Main() throws Exception {
      JTextField tf = new JTextField();
      getContentPane().add(tf);
      pack();

      tf.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            System.exit(0);
         }
      });
   }
 
   public static void main(String args[]) throws Exception {
      Main main = new Main();
      main.show();
   }
}

For international applications, you can determine the orientation using
the Locale:

      Locale arabic = new Locale("ar", "SA");
      jcomponent.setComponentOrientation(ComponentOrientation.getOrientation(arabic));

Creating a JLabel with the icon on top and text below

Here’s a complete example:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame
{
   JLabel label;
 
   public Main() {
      label = new JLabel("The Logo", new ImageIcon("d:\ESUSLOGO.gif"), 

SwingConstants.CENTER);
      label.setVerticalTextPosition(SwingConstants.BOTTOM);
      label.setHorizontalTextPosition(SwingConstants.CENTER);
      getContentPane().add(BorderLayout.CENTER, label);
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      setSize(300, 200);
   }
  
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
   }
}

Preventing the user from renaming files/directories in a JFileChooser

This is a hard task. I sat 3 hours to solve the problem for Jbuzzer. I do not know, if I solved the problem in a good way but it works.

Problem

The problem is, that deep inside of the UI of the JFileChooser – at the level of concrete implementation of the Look & Feel – the internal javax.swing.JList is instantiated without even keeping a member handle to it. It is done within a method that instantiates it, configures it (e.g.: with mouse listeners), adds it in a JPanel and returns that one.

The java jdk source code (1.4)

public class MetalFileChooserUI extends BasicFileChooserUI{
   private JPanel listViewPanel;
 
   public void installComponents(JFileChooser fc) {
      ...
      listViewPanel = createList(fc);
      ...
   }
 
   // A big don't: Hardcoded listeners 
   // in the UI implementation.
   protected JPanel createList(JFileChooser fc) {
      list = new JList() { <anonymous initialisation >};
      ...
      <b>list.addMouseListener(createSingleClickListener(fc,list));</b>
      ...
   }

   private MouseListener reateSingleClickListener(JFileChooser fc, JList list) 
   {
      return new SingleClickListener(list);
   }
 
   protected class SingleClickListener extends MouseAdapter {
      JList list;
      public void mouseClicked(MouseEvent e) {
         if (SwingUtilities.isLeftMouseButton(e)) {
            if (e.getClickCount() == 1) {
               JFileChooser fc = getFileChooser();
               int index = list.locationToIndex(e.getPoint());
               if ((!fc.isMultiSelectionEnabled() 
                   || fc.getSelectedFiles().length <= 1)
                   && index >= 0 
                   && list.isSelectedIndex(index)
                   && getEditIndex() == index 
                   && editFile == null) {
                      editFileName(index);
                   } 
               else {
                   ...
               }
            }

Solution

  1. Create your JFileChooser.

  • Run a search for it’s Component child of type JList.
  • Get the MouseListener of this JList whose class name contains “SingleClick” (I did not search other plaf packages: they might do the same bad thing but add the MouseListener for editing the JList in another way. This bugfix will only work for javax.swing.plaf.metal).
  • Remove that MouseListener from the retrieved JList.

    Code

    import javax.swing.JList;
    import java.awt.Component;
    import java.awt.Container;
    import javax.swing.JFileChooser;
    import java.awt.event.MouseListener;
     
    public class somename {
       ...
       /**
       * <p>
       * Hack to get the {@link List} of the {@link JFileChooser} 
       * instance used for loading sounds: 
       * We have to remove the "Single Click" listener 
       * that allows renaming files.
       * </p>
       */
       private JList searchJList(Container fileChooser)
       {
          JList ret = null;
          // First check, wether i am a JList:
          if (fileChooser instanceof JList){
              ret = (JList)fileChooser;
          }
          // Ok, me not: let's ask the children.
          else {
             Component[] children = fileChooser.getComponents();
             for(int i=children.length-1;i>=0;i--) {
                if (children[i] instanceof Container) {
                   ret = searchJList((Container)children[i]);
                   if(ret != null) {
                      break;
                   }
                }
             }
          }
    
          return ret;
       }
     
       // Just demo code! 
       public static void main(String[]args){
          JFileChooser load = new JFileChooser("/home/user/...");
          JList list = searchJList(this.openDialog);
          if (list!=null) {
             String listenerClassName;
             MouseListener[] listeners = list.getMouseListeners();
             for (int i=0;i< listeners.length;i++) {
                listenerCName = listeners[i].getClass().getName();
                if(listenerCName.indexOf("SingleClick")!= -1) {      
                   list.removeMouseListener(mouseListeners[i]);
                   break;
                }
             }
          }
          // Show the file chooser.
       }
    }
    

    Further examinations of other L&F packages could require changes. This has only be tested with javax.swing.plaf.metal.

    See the working example in Jbuzzer, a small fun-application for mapping sounds to keystrokes: http://sourceforge.net/projects/jbuzzer/.

  • Creating a JTable with fixed columns

    You can call the following method:

       table.getTableHeader().setResizingAllowed(false);
    

    However, be aware that this will disable resizing for all columns, and will still resize the columns proportionally when resizing the container in which the JTable is hosted. To fix the size of one column, you have to think about what behavior you want and override the method sizeColumnsToFit().

    Main.java:

    import javax.swing.table.*;
    import java.awt.event.*;
    import javax.swing.*;
    import java.util.*;
    import java.awt.*;
     
    public class Main extends JFrame {
       public Main() {
          super("TableModel Demonstration");
     
          // create our own custom TableModel
          WineTableModel wineModel = new WineTableModel();
          JTable table = new JTable(wineModel);
     
          // add rows to our TableModel, each row is represented as a Wine object
          wineModel.addWine(new Wine("Chateau Meyney, St. Estephe", "1994", 18.75f, true));
          wineModel.addWine(new Wine("Chateau Montrose, St. Estephe", "1975", 54.25f, true));
          wineModel.addWine(new Wine("Chateau Gloria, St. Julien", "1993", 22.99f, false));
          wineModel.addWine(new Wine("Chateau Beychevelle, St. Julien", "1970", 61.63f, false));
          wineModel.addWine(new Wine("Chateau La Tour de Mons, Margeaux", "1975", 57.03f, true));
          wineModel.addWine(new Wine("Chateau Brane-Cantenac, Margeaux", "1978", 49.92f, false));
     
     
          // don't allow resizing columns
          table.getTableHeader().setResizingAllowed(false);
     
     
          // create the scroll pane and add the table to it. 
          JScrollPane scrollPane = new JScrollPane(table);
     
          // add the scroll pane to this window.
          getContentPane().add(scrollPane, BorderLayout.CENTER);
     
          addWindowListener(new WindowAdapter() {
             public void windowClosing(WindowEvent e) {
                System.exit(0);
             }
          });
       }
     
       public static void main(String[] args) {
          Main main = new Main();
          main.pack();
          main.setVisible(true);
       }
    }
     
    // a simple object that holds data about a particular wine
    class Wine {
       private String  name;
       private String  vintage;
       private float   price;
       private boolean inStock;
     
       public Wine(String name, String vintage, float price, boolean inStock) {
          this.name = name;
          this.vintage = vintage;
          this.price = price;
          this.inStock = inStock;
       }
     
       public String getName()     { return name; }
       public String getVintage()  { return vintage; }
       public float  getPrice()    { return price; } 
       public boolean getInStock() { return inStock; }
     
       public String toString() { 
          return "[" + name + ", " + vintage + ", " + price + ", " + inStock + "]"; }
    }
     
    class WineTableModel extends AbstractTableModel {
       // holds the strings to be displayed in the column headers of our table
       final String[] columnNames = {"Name", "Vintage", "Price", "In stock?"};
     
       // holds the data types for all our columns
       final Class[] columnClasses = {String.class, String.class, Float.class, Boolean.class};
     
       // holds our data
       final Vector data = new Vector();
      
       // adds a row
       public void addWine(Wine w) {
          data.addElement(w);
          fireTableRowsInserted(data.size()-1, data.size()-1);
       }
     
       public int getColumnCount() {
          return columnNames.length;
       }
             
       public int getRowCount() {
          return data.size();
       }
     
       public String getColumnName(int col) {
          return columnNames[col];
       }
     
       public Class getColumnClass(int c) {
          return columnClasses1;
       }
     
       public Object getValueAt(int row, int col) {
          Wine wine = (Wine) data.elementAt(row);
          if (col == 0)      return wine.getName();
          else if (col == 1) return wine.getVintage();
          else if (col == 2) return new Float(wine.getPrice());
          else if (col == 3) return new Boolean(wine.getInStock());
          else return null;
       }
     
       public boolean isCellEditable(int row, int col) {
          return false;
       }
    }