Re: Closable Tabs in JTabbedPane

A

Alan Moore

Yesterday I thought see what I could find on "Closable Tabs in
JTabbedPane". Our own framework library at work did not have anything
useful and neither our COTS libraries. A quick search of the group was
equally unhelpful. At any rate here is a long overdue contribution
that I threw together as a quick investigation of how this could be
done; although, there is likely a more elegant solution out there
still. I have tried to capture the platform look and feel without too
many dependencies on the UI classes. I have found, in general, that
however much fun it can be (NOT) playing with custom UI classes or UI
hacks are often broken with new releases of the JDK.

Unfortunately, they've managed to break it anyway, despite your
precautions. When I run this code under Tiger-beta1, it comes out
thoroughly mangled in all three L&F's. Apparently, it's the new Ocean
theme causing that, because if I comment out the lines that create the
Metal example, the other two paint okay. However, the Motif example
can't seem to find the specified icon (but if I click on the tiny
square that it paints instead, it does close the tab). The Windows
example is a little flaky, in that the close buttons don't always work
the first time I click them. (It also tends to throw NPE's, but
that's due to a bug I've already reported.)

Under 1.4.2, the close buttons don't work if you use the
SCROLL_TAB_LAYOUT option. And, of course, there's no way to make it
paint the icon to the right of the text (where it belongs, IMO). This
is the most elegant attempt I've seen at solving this problem, but
you're trying to do the impossible. There isn't going to be a
satisfactory solution until they rewrite JTabbedPane from scratch. In
fact, they said they were going to do just that for Tiger, but they
seem to have reneged on that promise.
 
D

Dan Andrews

Alan Moore said:
Under 1.4.2, the close buttons don't work if you use the
SCROLL_TAB_LAYOUT option. And, of course, there's no way to make it
paint the icon to the right of the text (where it belongs, IMO). This
is the most elegant attempt I've seen at solving this problem, but
you're trying to do the impossible. There isn't going to be a
satisfactory solution until they rewrite JTabbedPane from scratch. In
fact, they said they were going to do just that for Tiger, but they
seem to have reneged on that promise.

Thanks for the comments. There is another minor problem that I have
noticed too. When closing a tab you will need to remove the mouse
listener.

/**
* Mouse clicked check to close tab if required.
* @param e IN the MouseEvent object.
*/
public void mouseClicked( MouseEvent e )
{

if( _bounds.contains( e.getX(), e.getY() ) )
{
// *Remove* the listener
_parentTabbedPane.removeMouseListener( this );
_parentTabbedPane.remove( _tabbedComponent );
}
}
 
A

Alan Moore

Thanks for the comments. There is another minor problem that I have
noticed too. When closing a tab you will need to remove the mouse
listener.

/**
* Mouse clicked check to close tab if required.
* @param e IN the MouseEvent object.
*/
public void mouseClicked( MouseEvent e )
{

if( _bounds.contains( e.getX(), e.getY() ) )
{
// *Remove* the listener
_parentTabbedPane.removeMouseListener( this );
_parentTabbedPane.remove( _tabbedComponent );
}
}

What I prefer to do is to put a Close button in the toolbar, way over
at the right end (under the window-close button), that closes
whichever tab is on top. I also have a mouse listener that brings up
a popup menu whenever the user right-clicks on a tab. Choosing the
Close menuitem lets the user close that pane without bringing it to
the top first. (I actually have to use the low-level processMouseEvent
method to achieve that.) Having a Close button in every tab has
always seemed like a waste of space to me anyway.
 
W

winslave

Well I've done this by extending ImageIcon (similar to the code
you provided) and JPanel
and adding a mouse listener to the JTabbedPane.
My custom JPanel has a getCloseIcon() method used to get a reference
to the close icon. In the mouseClicked
event I do a
public void mousePressed(MouseEvent e) {
try{
MyFilePanel mfp=(MyFilePanel)tabbedPane.getSelectedComponent();
MyTabXIcon mtx=mfp.getCloseIcon();
if(mtx.getBounds().contains(e.getPoint()))
{
tabbedPane.remove(tabbedPane.getSelectedIndex());
}
}catch(Exception ex){}
}
 
C

chrismurphy

Hi Alan,

Would you be able to post that low-level processMouseEvent method you
mentioned? I'm up to the same place myself and well, if someone else has
already done it ...

thanks - Chris Murphy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top