Closable Tabs in a Tabbed Pane
Hi,
I am working on an application, where i need to have an "x" mark on the Tabs, clicking on which, i should be able to close the Tab. (Some what similar to the Tabbed pages we see in Eclipse)
This is Java 1.5 Application. Is there a way to add a button or an Icon to the Tab, and attach an action listener to it, in such a way that the tab page will be closed upon clicking on the button or icon?
Please Help.
thanks,
vani
[461 byte] By [
vani_ha] at [2007-10-3 2:45:07]

Here is one possible solution that I adapted from a posting on the Internet by adding logic to support getting the user to confirm the close.
Use this code when you add the tab:tabbedPane.addTab(theTitle, new CloseTabIcon(), theComponent, tooltip);
And add this class to your application:import java.awt.Component;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JTabbedPane;
/**
* This class encapsulates an icon that can be added to the selector tab of a JTabbedPane to allow
* clicks upon it to close its owning tab.
*
* Created on 19/06/2006 by Tim Ryan
*/
public class CloseTabIcon implements Icon {
private final Icon icon;
private JTabbedPane tabbedPane = null;
private transient Rectangle position = null;
/**
* Creates a new instance of CloseTabIcon.
*/
public CloseTabIcon() {
this.icon = new ImageIcon(CloseTabIcon.class.getResource("images/CloseTab.gif"));
}
/**
* when painting, remember last position painted so we can see if the user clicked on the icon.
*/
public void paintIcon(Component component, Graphics g, int x, int y) {
// Lazily create a link to the owning JTabbedPane and attach a listener to it, so clicks on the
// selector tab can be intercepted by this code.
if (tabbedPane == null) {
tabbedPane = (JTabbedPane) component;
tabbedPane.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
// asking for isConsumed is *very* important, otherwise more than one tab might get closed!
if (! e.isConsumed() && position.contains(e.getX(), e.getY())) {
Macro macro = (Macro) tabbedPane.getSelectedComponent();
boolean close = true;
if (macro.isModified()) {
int result = JOptionPane.showConfirmDialog(PlayAct.getInstance().getFrame(), "The macro " + macro.getTitle()
+ " is modified but unsaved.\nDo you wish to save before closing?", "CONFIRM",
JOptionPane.YES_NO_CANCEL_OPTION);
if (result == JOptionPane.YES_OPTION) {
macro.save();
} else if (result == JOptionPane.CANCEL_OPTION) {
close = false;
}
}
if (close) {
tabbedPane.remove(macro);
}
e.consume();
}
}
});
}
position = new Rectangle(x, y, getIconWidth(), getIconHeight());
icon.paintIcon(component, g, x, y);
}
/**
* just delegate
*/
public int getIconWidth() {
return icon.getIconWidth();
}
/**
* just delegate
*/
public int getIconHeight() {
return icon.getIconHeight();
}
}
> But none of them work for the Scrollable Tab layout and when the tabs are at the BOTTOM
it's fairly simple to get this to work when at the bottom, the problem is with both
wrap and scroll layouts (affects TOP the same way)
the icon rectangle coords, when in a wrap/scroll layout, do not match the
clickable area coords available to the mouse.
to understand, use any of the code you have found, adjust for say 12 tabs,
set them to the TOP. Do not use wrap or scroll layout. run the program, drag
the frame wide enough to display the 12 tabs. Now click any of the tabs and they
will all be closeable.
change the code to a scroll layout, recompile and run again. You can close
the first couple (because the screen coords match), but the rest do not close.
when you run the program, immediately scroll a few tabs to the right, click one,
it will not close, but the tab (0,1,2 etc) that was in that position on opening will close.
if you change to the bottom, you have to modify the rect coords to increase y
by the tabpane's preferredSize.height and deduct the tabarea rect.height.
I would say it is certainly possible to achieve what you want, but it will take a
lot of work/code to get the icon's coords to match me.getX() and me.getY().
It might be a whole lot easier if you could use java 1.6, where I believe tabpanes
can now have components in the tab area, if so, a JButton should do exactly what you want