Setting the background color of the tabs of a JTabbedPane

You can set the background color using the method setBackgroundAt. However, this will only change the background of the tabs that are not selected. You can’t change the background of the selected tab unless you change the look and feel “TabbedPane.selected” property. This would change all JTabbedPanes that you have instantiated. A bug was filed for this: http://developer.java.sun.com/developer/bugParade/bugs/4230649.html.

import javax.swing.plaf.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JPanel {                     
  public Main() {
    setLayout(new BorderLayout());
    
    UIManager.put("TabbedPane.selected", Color.green);
    
    JTabbedPane tabbedPane = new JTabbedPane();
    for (int i=0;i<10;i++) {
      tabbedPane.addTab("Tab #" + i, new JLabel("Tab #" + i));
      tabbedPane.setBackgroundAt(i, new Color(25*i, 25*i, 25*i));
    }
    add(tabbedPane, BorderLayout.CENTER);
  }
  
  JPanel createPane(String s) {
    JPanel p = new JPanel();
    p.add(new JLabel(s));
    return p;
  }
  
  public static void main(String[] args) {
    JFrame frame = new JFrame("JTabbedPane Selected Color Demonstration");
    frame.addWindowListener( new WindowAdapter() {
      public void windowClosing( WindowEvent e ) {
        System.exit(0);
      }
    });
    frame.getContentPane().add(new Main());
    frame.setSize(200, 100);
    frame.setVisible(true);
  }
}

Creating a scrollable JInternalFrame

Main.java:

import javax.swing.border.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.net.*;
 
public class Main extends JFrame {
   JDesktopPane desktop;
   int nframes = 0;
 
   public Main() {
      getContentPane().setLayout(new BorderLayout());
      desktop = new JDesktopPane(); 
      createInternalFrame();
      getContentPane().add(BorderLayout.CENTER, desktop);
      setJMenuBar(createMenuBar());
  
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   
      setTitle("Transparent JInternalFrame Demonstration");
      setSize(new Dimension(400, 400));
   }
 
   protected JMenuBar createMenuBar() {
      JMenuBar menuBar = new JMenuBar();
 
      JMenu menu = new JMenu("JDesktopPane");
      JMenuItem menuItem1 = new JMenuItem("Create new JInternalFrame");
      menuItem1.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            createInternalFrame();
         }
      });
      menu.add(menuItem1);
      menuBar.add(menu);
 
      return menuBar;
   }
 
   protected void createInternalFrame() {
      JInternalFrame frame = new JInternalFrame("InternalFrame", 
         true,    // resizable
         true,    // closable
         true,    // maximizable
         true);   // iconifiable
      frame.setVisible(true); 
      desktop.add(frame);
      frame.setSize(200, 200);
      frame.setLocation(30*nframes, 30*nframes);
      nframes++;
      frame.setContentPane(new JScrollPane(new MyPanel(new ImageIcon("mong.jpg"))));
 
      try {
         frame.setSelected(true);
      } catch (java.beans.PropertyVetoException e) {}
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.show();
   }
}
 
class MyPanel extends JPanel
{
   private ImageIcon bgImage;
 
   public MyPanel(ImageIcon bgImage) {
      setLayout(new GridLayout(20, 1));
      setBorder(new EmptyBorder(10, 10, 10, 10));
      for (int i=0; i<10; i++) {    
         add(new JLabel("JLabel #" + i));
         add(new JTextField(10));
      }
 
      this.bgImage = bgImage;
   }
 
   public void paintComponent(Graphics g) {    
      Dimension d = getSize();      
      g.drawImage(bgImage.getImage(), 0, 0, (int)d.getWidth(), (int)d.getHeight() , this);          
   }
}

Changing the mouse pointer to a hand cursor when the mouse moves over a JButton

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame
{
   private Cursor handCursor = new Cursor(Cursor.HAND_CURSOR);
   private Cursor defaultCursor = new Cursor(Cursor.DEFAULT_CURSOR);
 
   public static void main(String []args) {
      Main main = new Main();
      main.show();
   }
 
   public Main() {
      JButton button = new JButton("Move mouse over this button!");
      button.addMouseListener(new MouseAdapter() {
         public void mouseEntered(MouseEvent me) {
            setCursor(handCursor);
         }
         public void mouseExited(MouseEvent me) {
            setCursor(defaultCursor);
         }
      });
  
      getContentPane().setLayout(new FlowLayout(FlowLayout.CENTER));
      getContentPane().add(button);
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            System.exit(0);
         }
      });
 
      setSize(300, 100);
   }  
}

Getting the selected item(s) from a JList

There are several functions to determine the selected value(s) of a JList:

  • getSelectedIndex() returns the first selected index
  • getSelectedIndices() returns all of the selected indices
  • getSelectedValue() returns the first selected value
  • getSelectedValues() returns all of the selected values

Here’s an example:

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<20; i++) {
         v.addElement("Item #" + i);
      }
 
      final JList list = new JList(v);
      getContentPane().add(new JScrollPane(list));
      JButton button = new JButton("Show selected items");
      getContentPane().add(button);
      button.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) { 
            System.out.println("Selected values:");
            Object[] oarr = list.getSelectedValues();
            for (int i=0; i<oarr.length; i++) {
               System.out.println(oarr[i]);
            }
 
            System.out.println("Selected indices:");
            int[] iarr = list.getSelectedIndices();
            for (int i=0; i<iarr.length; i++) {
               System.out.println(iarr[i]);
            }
         }
      });
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent event) {
            System.exit(0);   
         }      
      });
 
      setSize(200, 250);
   }
   
   public static void main(String[] args) {
      (new Main()).show();
   }
}

Allowing multiple selections in a JList

A JList has three different selection modes:

1) SINGLE_SELECTION: allows only one item to be selected at a time

2) SINGLE_INTERVAL_SELECTION: allows contiguous items to be selected at a time

3) MULTIPLE_INTERVAL_SELECTION: (default) allows any combination of items to be selected at a time

Following example shows you how to apply them
Main.java:

import javax.swing.event.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
  
public class Main extends JFrame implements ActionListener {
   JList list; 
 
   public Main() {
      getContentPane().setLayout(new BorderLayout());
 
      final DefaultListModel listModel = new DefaultListModel();   
 
      // populate listmodel
      for (int i=0; i<10; i++) {
         listModel.addElement("list item #" + i);
      }
 
      list = new JList(listModel); 
      getContentPane().add(BorderLayout.CENTER, new JScrollPane(list));    
 
      JPanel panel = new JPanel(new GridLayout(3, 1));
      JRadioButton rb1 = new JRadioButton("SINGLE_SELECTION");
      rb1.addActionListener(this);
      JRadioButton rb2 = new JRadioButton("SINGLE_INTERVAL_SELECTION");
      rb2.addActionListener(this);
      JRadioButton rb3 = new JRadioButton("MULTIPLE_INTERVAL_SELECTION");
      rb3.addActionListener(this);
      ButtonGroup bg = new ButtonGroup();
      bg.add(rb1);
      bg.add(rb2);
      bg.add(rb3);
      panel.add(rb1);
      panel.add(rb2);
      panel.add(rb3);
      getContentPane().add(BorderLayout.EAST, panel);
  
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent event) {
            System.exit(0);   
         }      
      });
 
      pack();
   }
 
   public void actionPerformed(ActionEvent ae) {
      if (ae.getActionCommand().equals("SINGLE_SELECTION"))
         list.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
      else if (ae.getActionCommand().equals("SINGLE_INTERVAL_SELECTION"))
         list.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
      else if (ae.getActionCommand().equals("MULTIPLE_INTERVAL_SELECTION"))
         list.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
   }
   
   public static void main(String[] args) {
      (new Main()).show();
   }
}

Detecting a value change of my JSlider

Add a ChangeListener and add behavior to its method stateChanged.

Main.java:

import javax.swing.event.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
  
public class Main extends JFrame { 
   JSlider slider;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });   
 
      slider = new JSlider(JSlider.HORIZONTAL, 0, 20, 1);
      slider.addChangeListener(new ChangeListener() {
         public void stateChanged(ChangeEvent ce) {
            repaint();
         }
      });
 
      slider.setMajorTickSpacing(1);
      slider.setPaintTicks(true);
      slider.setPaintLabels(true);
 
      getContentPane().setLayout(new BorderLayout());
      getContentPane().add(BorderLayout.NORTH, slider);
   } 
 
   public void paint(Graphics g) {
      super.paint(g);
  
      Graphics2D g2d = (Graphics2D) g;
 
      g2d.setFont(new Font("Serif", Font.BOLD, 36));
      g2d.drawString(""+slider.getValue(), 200, 130);
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 150);
      main.setVisible(true);
   }
}

Creating a numeric-only JTextfield

Here’s the code for a Swing component that only accepts digits.

Main.java:

import javax.swing.text.*;
import java.awt.event.*;
import javax.swing.*;
import java.text.*;
import java.awt.*;
   
public class Main extends JFrame {
   public Main() {
      getContentPane().setLayout(new GridLayout(2, 1));
 
      final JPasswordField passwordField = new JPasswordField(20);
      final JTextField textField = new JTextField(20);
      getContentPane().add(new NumberTextField(5));
      getContentPane().add(new NumberTextField(123, 7));
  
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent event) {
            System.exit(0);   
         }      
      });
 
      pack();
   }
 
   public static void main(String[] args) {
      (new Main()).show();
   }
}
 
class NumberTextField extends JTextField
{
   private NumberFormat nf;
 
   public NumberTextField(int cols) {
      super(cols);
      nf = NumberFormat.getNumberInstance();
   }
 
   public NumberTextField(int value, int cols) {
      this(cols);
      setValue(value);
   }
 
   public int getValue() {
      int n = 0;
      try {
         n = nf.parse(getText()).intValue();
      }
      catch(ParseException e) { }
      return n;
   }
 
   public void setValue(int value) {
      setText(nf.format(value));
   }
 
   protected Document createDefaultModel() {
      return new NumberDocument();
   }
 
   protected class NumberDocument extends PlainDocument {
      public void insertString(int offset, String string, AttributeSet as) 
            throws BadLocationException  {
         char [] src = string.toCharArray();
         char [] dest = new char[src.length];
         int count=0;
         for (int i=0; i < src.length; i++) {
            if (Character.isDigit(src[i])) 
               dest[count++] = src[i];
         }
         super.insertString(offset, new String(dest, 0, count), as);
      }
   }
}

Creating a multi-line text tooltip for a JLabel

An easy way is to have your tooltip text to be HTML:

   label.setToolTipText("<html>This is a two-line<br> tooltip text!</html>");

as in following example:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
                            
public class Main extends JFrame
{ 
   public Main() {
      getContentPane().setLayout(new FlowLayout());
      JLabel label = new JLabel("Mouse-over me!");
      getContentPane().add(label);
                         
      label.setToolTipText("<html>This is a two-line<br> tooltip text!</html>");
                         
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });      
                           
      setSize(new Dimension(200, 200));
   } 
                         
   public static void main(String[] args) throws Exception {
      Main main = new Main();
      main.setVisible(true);
   }
}

Adding a JProgressBar inside a JTable cell

A JTable registers default renderers for a Number, Date, ImageIcon, Boolean and Object. If you want to render another component, you have to create a custom class that implements TableCellRenderer and register it with the method setDefaultRenderer on the JTable object.

The following example creates a JTable where every row displays data from a Download object. A download object is a thread that mimics the behavior of downloading a file by increasing the number of downloaded bytes (progress) with a random value. Using the Observable-Observer pattern, the download object notifies the table model whenever the progress of downloading has changed.

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(&quot;TableModel JProgressBar Demonstration&quot;);
 
      // create our own custom TableModel
      DownloadTableModel downloadModel = new DownloadTableModel();
      JTable table = new JTable(downloadModel);
 
      // add rows to our TableModel, each row is represented as a Download object
      downloadModel.addDownload(new Download(&quot;linuxmandrake.zip&quot;, 1234567));
      downloadModel.addDownload(new Download(&quot;flash5.exe&quot;, 56450000));
      downloadModel.addDownload(new Download(&quot;jdk1.2.2-007.zip&quot;, 20000000));
 
      // render the columns with class JProgressBar as such
      ProgressBarRenderer pbr = new ProgressBarRenderer(0, 100);
      pbr.setStringPainted(true);
      table.setDefaultRenderer(JProgressBar.class, pbr);
   
      // increase the height of the rows a bit
      table.setRowHeight((int) pbr.getPreferredSize().getHeight());
 
      // 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 download
// it starts a thread and increases the progress of &quot;downloading&quot;
// in a random manner
class Download extends Observable implements Runnable {
   private Thread  thisThread;
 
   private String  filename;
   private int     filesize;
   private float   progress;
 
   public Download(String filename, int filesize) {
      this.filename = filename;
      this.filesize = filesize;
      progress = 0.0f;
      thisThread = new Thread(this);
      thisThread.start();
   }
 
   public String getFilename() { return filename; }
   public int    getFilesize() { return filesize; }
   public float  getProgress() { return progress; }
 
   public String toString() { 
      return &quot;[&quot; + filename + &quot;, &quot; + filesize + &quot;, &quot; + progress + &quot;]&quot;; }

   public void run() {
      Random r = new Random();
      int count = 0;
      while (count &lt; filesize) {
         int random = Math.abs(r.nextInt() % 100000);
         count += random;
         if (count &gt; filesize) count = filesize; 
         progress = ((float) count / filesize) * 100;
 
         // notify table model (and all other observers)
         setChanged();
         notifyObservers(this);       
 
         try { thisThread.sleep(500); } catch(InterruptedException e) { }
      }
   }
}
 
class DownloadTableModel extends AbstractTableModel implements Observer {
   // holds the strings to be displayed in the column headers of our table
   final String[] columnNames = {&quot;Filename&quot;, &quot;Filesize&quot;, &quot;Progress&quot;};
 
   // holds the data types for all our columns
   final Class[] columnClasses = {String.class, Integer.class, JProgressBar.class};
 
   // holds our data
   final Vector data = new Vector();
  
   // adds a row
   public void addDownload(Download d) {
      data.addElement(d);
   
      // the table model is interested in changes of the rows
      d.addObserver(this);
      fireTableRowsInserted(data.size()-1, data.size()-1);
   }
 
   // is called by a download object when its state changes
   public void update(Observable observable, Object o) {
      int index = data.indexOf(o);
      if (index != -1) 
         fireTableRowsUpdated(index, index);
   }
 
   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) {
      Download download = (Download) data.elementAt(row);
      if (col == 0)      return download.getFilename();
      else if (col == 1) return new Integer(download.getFilesize());
      else if (col == 2) return new Float(download.getProgress());
      else return null;
   }
 
   public boolean isCellEditable(int row, int col) {
      return false;
   }
}
 
// a table cell renderer that displays a JProgressBar
class ProgressBarRenderer extends JProgressBar implements TableCellRenderer {
   public ProgressBarRenderer() {
      super();
   }
 
   public ProgressBarRenderer(BoundedRangeModel newModel) {
      super(newModel);
   }
 
   public ProgressBarRenderer(int orient) {
      super(orient);
   } 
 
   public ProgressBarRenderer(int min, int max) {
      super(min, max);
   }
 
   public ProgressBarRenderer(int orient, int min, int max) {
      super(orient, min, max);
   }
 
   public Component getTableCellRendererComponent(
      JTable table, Object value, boolean isSelected, boolean hasFocus,
      int row, int column) {
           
      setValue((int) ((Float) value).floatValue());
 
      return this;
   }
}