JDK-4253819 : If you remove ANY JTabbedPane tab except the last one there is NO state change!
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.2.2
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 1999-07-13
  • Updated: 2003-03-12
  • Resolved: 2003-03-06
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
5.0 tigerFixed
Related Reports
Relates :  
Relates :  

Name: skT88420			Date: 07/13/99

1. Steps:

Run this program (code below) and close any tab except
the tab which is currently the last tab.  There will be NO
changeEvent fired.  In my sample code, changeEvents cause a
BANG followed by a number to be printed on System.out so you can
easily see which events cause changeEvents and which don't.

The reason why this happens probably is that the concept of
a state change must be INCORRECTLY based on which tab
INDEX is selected, rather than which ACTUAL TAB is selected.
So there is no changeEvent when you remove a tab which is not
the last tab since it does NOT cause a selected index change!!!

2. Source code:

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

public class JTabbedPaneBug extends JFrame {
	public JTabbedPaneBug() {
		super("If you remove ANY TAB except the last tab there is NO state change!");
		setSize(800, 300);
		Container mainContentPane = getContentPane();
		mainContentPane.setLayout(new BorderLayout(0,0));
		mainContentPane.add("Center", pain);
		JButton one = new JButton(REMOVE);
		JButton two = new JButton(REMOVE);
		JButton three = new JButton(REMOVE);
		JButton four = new JButton(REMOVE);
		JButton five = new JButton(REMOVE);
		JButton six = new JButton(REMOVE);
		JButton seven = new JButton(REMOVE);
		one.addActionListener(new Foo());
		two.addActionListener(new Foo());
		three.addActionListener(new Foo());
		four.addActionListener(new Foo());
		five.addActionListener(new Foo());
		six.addActionListener(new Foo());
		seven.addActionListener(new Foo());
		pain.addTab("one", one);
		pain.addTab("two", two);
		pain.addTab("three", three);
		pain.addTab("four", four);
		pain.addTab("five", five);
		pain.addTab("six", six);
		pain.addTab("seven", seven);
	private static String REMOVE = "Click anywhere to remove the panel!";
	PaneAndSuffering pain = new PaneAndSuffering();
	class PaneAndSuffering extends JTabbedPane {
		protected void fireStateChanged() {
			System.out.println("BANG " + bangCount++);
		private int bangCount = 0;
	class Foo implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			//if you can click the button it's the selected index
	public static void main(String[] args) {
		JTabbedPaneBug jtb = new JTabbedPaneBug();
(Review ID: 85497) 

CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger FIXED IN: tiger INTEGRATED IN: tiger tiger-b03

EVALUATION This is happening due to the selection model used in the JTabbedPane class. The model only seems to fire state changes when the selected index changes. That's why you don't get any state changes if the selected tab stays at the same index. If you select the last tab and press the button to remove the tab you will get a state changed event for each tab. This behavior is inconsistent. ###@###.### 2001-11-17 Name: omR10226 Date: 02/25/2003 JTabbedPane represents an integer selection and fires change notification only when that integer changes. When a last tab is deleted the selected index is decreased by one and stateChanged is fired. stateChanged() is fired only when a selected index is changed, independently of a selected content. The bug will be closed as will not fix. ======================================================================

WORK AROUND Name: skT88420 Date: 07/13/99 Subclass JTabbedPane and override fireStateChanged(). Have your overriden method call a method to actually do the real work, and have this doTheWork() method also get called when any other method causes a tab in the JTabbedPane subclass to be removed. protected void fireStateChanged() { super.fireStateChanged(); doTheWork();//this method should get called when a tab is removed } ====================================================================== Name: omR10226 Date: 02/25/2003 The selection state after a call of removeTabAt() is predictable easy, so if you need to react on a change of the selected tab after remove/insert (the selected index isn't changed and stateChanged() isn't called, but the visible content is changed) you may use the following way: you may react on insert/remove directly after call of it; for example, you may write your method insert/remove void removeTabAt(int index) { tabbedPane.removeTabAt(index); ... reaction on remove ... } ======================================================================