Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

JavaWorld Daily Brew

Placing Components on Tabs

 


by John Zukowski

The JTabbedPane component is a special Swing
container that accepts components to be placed within a panel for
each tab. Select a tab to see that tab's components. Technically
speaking, one component is associated with each tab. However, that
component is typically a panel that contains others. Identification
for each tab is done with title text and an icon, settable per tab.
The first Core Java Technologies Tech Tip to discuss the
JTabbedPane component was published in July 2001, with
a simple introductory tip.

The methods of JTabbedPane to support the use of
components on tabs are as follows:

  • public void setTabComponentAt(int index, Component component)
  • public Component getTabComponentAt(int index)
  • public int indexOfTabComponent(Component tabComponent)

The first method associates the component with a tab; the second
gets it back; and the last one tells you which tab is associated
with the component, if any. Typically, you use only the first
method, but the others are available.

To get started with the task at hand, it is helpful to have an
Icon implementation that draws a little x on it. You could just use
the letter x as the button label, but you should avoid that option.
Typically, when a user sees an x in a box, this
signals a command to close a window, so it serves as a good
indicator for closing a tab.

class CloseIcon implements Icon {
  public void paintIcon(Component c, Graphics g, int x, int y) {
    g.setColor(Color.RED);
    g.drawLine(6, 6, getIconWidth() - 7, getIconHeight() - 7);
    g.drawLine(getIconWidth() - 7, 6, 6, getIconHeight() - 7);
  }
  public int getIconWidth() {
    return 17;
  }
  public int getIconHeight() {
    return 17;
  }
}

Before creating the special tab component, let's put together the
program's framework, one that creates a frame with a
JTabbedPane on it and adds a number of tabs:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class CloseTabs {
  public static void main(String args[]) {
    Runnable runner = new Runnable() {
      public void run() {
        JFrame frame = new JFrame("JTabbedPane");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JTabbedPane jtp = new JTabbedPane();
        frame.add(jtp, BorderLayout.CENTER);
        for (int i=0; i<5; i++) {
          JButton button = new JButton("Card " + i);
          jtp.add("Btn " + i, button);
          // new CloseTabButton(jtp, i);
        }
        frame.setSize(400, 200);
        frame.setVisible(true);
      }
    };
    EventQueue.invokeLater(runner);
  }
}

This program creates five tabs, each with a JButton
on it. The tab title is "Btn" followed by the tab position.



The program will run fine without doing anything else, but it
doesn't have the close button on each tab. To add a close button to
the tab, you need to retain the tab's title text and icon, while
adding a button with the CloseIcon previously shown.
(The
example does not use the tab's icon, but the class definition
includes one so that it can be reused beyond this example.) As the
final part of the definition, you need an
ActionListener for the button to handle when it is
pressed, so that when the user presses the button, the tab is
removed from the pane.

class CloseTabButton extends JPanel implements ActionListener {
  private JTabbedPane pane;
  public CloseTabButton(JTabbedPane pane, int index) {
    this.pane = pane;
    setOpaque(false);
    add(new JLabel(
        pane.getTitleAt(index),
        pane.getIconAt(index),
        JLabel.LEFT));
    Icon closeIcon = new CloseIcon();
    JButton btClose = new JButton(closeIcon);
    btClose.setPreferredSize(new Dimension(
        closeIcon.getIconWidth(), closeIcon.getIconHeight()));
    add(btClose);
    btClose.addActionListener(this);
    pane.setTabComponentAt(index, this);
  }
  public void actionPerformed(ActionEvent e) {
    int i = pane.indexOfTabComponent(this);
    if (i != -1) {
      pane.remove(i);
    }
  }
}

You can now reuse the CloseTabButton in your own
tabbed panes.



For more information on the use of tabbed panes, see the How to Use Tabbed
Panes
lesson in The Java Tutorial.