While perusing a newsgroup I found a simple subclass of JTabbedPane that
includes an X icon for deleting tabs. However, when I tried it I
periodically get ArrayIndexOutOfBounds exceptions on the event thread when
deleting tabs - not sure why. Stack trace and code below.
Thanks in Advance,
Mike
Exception in thread "AWT-EventQueue-0"
java.lang.ArrayIndexOutOfBoundsException: 0
at javax.swing.plaf.basic.BasicTabbedPaneUI.getTabBounds(Unknown Source)
at javax.swing.plaf.basic.BasicTabbedPaneUI.getTabBounds(Unknown Source)
at
com.sun.java.swing.plaf.windows.WindowsTabbedPaneUI.setRolloverTab(Unknown
Source)
at
javax.swing.plaf.basic.BasicTabbedPaneUI$TabbedPaneLayout.layoutContainer(Unknown
Source)
at java.awt.Container.layout(Unknown Source)
at java.awt.Container.doLayout(Unknown Source)
at java.awt.Container.validateTree(Unknown Source)
at java.awt.Container.validateTree(Unknown Source)
at java.awt.Container.validate(Unknown Source)
at javax.swing.RepaintManager.validateInvalidComponents(Unknown Source)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown
Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
---------------------------
public class JTabbedPaneWithCloseIcons extends JTabbedPane implements
MouseListener {
public JTabbedPaneWithCloseIcons() {
super();
addMouseListener(this);
}
public void addTab(String title, Component component) {
this.addTab(title, component, null);
}
public void addTab(String title, Component component, Icon extraIcon) {
super.addTab(title, new CloseTabIcon(extraIcon), component);
}
public void addTab(String title, Icon extraIcon, Component component,
String tip) {
super.addTab(title, new CloseTabIcon(extraIcon), component, tip);
}
public void insertTab(String title, Icon extraIcon, Component component,
String tip, int index) {
super.insertTab(title, extraIcon, component, tip, index);
}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {
final int tabNumber=getUI().tabForCoordinate(this, e.getX(), e.getY());
if (tabNumber < 0) return;
Rectangle rect=((CloseTabIcon)getIconAt(tabNumber)).getBounds();
if (rect.contains(e.getX(), e.getY())) {
//the tab is being closed
this.removeTabAt(tabNumber);
}
}
}
/**
* The class which generates the 'X' icon for the tabs. The constructor
* accepts an icon which is extra to the 'X' icon, so you can have tabs
* like in JBuilder. This value is null if no extra icon is required.
*/
class CloseTabIcon implements Icon {
private int x_pos;
private int y_pos;
private int width;
private int height;
private Icon fileIcon;
public CloseTabIcon(Icon fileIcon) {
this.fileIcon=fileIcon;
width=16;
height=16;
}
public void paintIcon(Component c, Graphics g, int x, int y) {
this.x_pos=x;
this.y_pos=y;
Color col=g.getColor();
g.setColor(Color.black);
int y_p=y+2;
g.drawLine(x+1, y_p, x+12, y_p);
g.drawLine(x+1, y_p+13, x+12, y_p+13);
g.drawLine(x, y_p+1, x, y_p+12);
g.drawLine(x+13, y_p+1, x+13, y_p+12);
g.drawLine(x+3, y_p+3, x+10, y_p+10);
g.drawLine(x+3, y_p+4, x+9, y_p+10);
g.drawLine(x+4, y_p+3, x+10, y_p+9);
g.drawLine(x+10, y_p+3, x+3, y_p+10);
g.drawLine(x+10, y_p+4, x+4, y_p+10);
g.drawLine(x+9, y_p+3, x+3, y_p+9);
g.setColor(col);
if (fileIcon != null) {
fileIcon.paintIcon(c, g, x+width, y_p);
}
}
public int getIconWidth() {
return width + (fileIcon != null? fileIcon.getIconWidth() : 0);
}
public int getIconHeight() {
return height;
}
public Rectangle getBounds() {
return new Rectangle(x_pos, y_pos, width, height);
}
}
opalpa@gmail.com opalinski from opalpaweb - 23 Feb 2006 23:48 GMT
swing operations need be in swing thread.
Opalinski
opalpa@gmail.com
http://www.geocities.com/opalpaweb/
Michael - 23 Feb 2006 23:52 GMT
Can you elaborate please...I tried wrapping the call to
this.removeTabAt(tabNumber); in SwingUtilities.invokeLater(), but that
didn't help.
Thanks,
Mike
<opalpa@gmail.com> wrote in message
news:1140738511.976085.215820@u72g2000cwu.googlegroups.com...
> swing operations need be in swing thread.
>
> Opalinski
> opalpa@gmail.com
> http://www.geocities.com/opalpaweb/
opalpa@gmail.com opalinski from opalpaweb - 24 Feb 2006 00:21 GMT
What happens when you put all swing operations in swing thread? All
the addTab calls, the place where you create Panel, call pack,
setVisible, and everything else swing.
Tracking this down is a pain.
Opalinski
opalpa@gmail.com
http://www.geocities.com/opalpaweb/