United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-4253819 : If you remove ANY JTabbedPane tab except the last one there is NO state change!

Details
Type:
Bug
Submit Date:
1999-07-13
Status:
Closed
Updated Date:
2003-03-12
Project Name:
JDK
Resolved Date:
2003-03-06
Component:
client-libs
OS:
generic
Sub-Component:
javax.swing
CPU:
generic
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.2.2
Fixed Versions:
5.0 (tiger)

Related Reports
Relates:
Relates:

Sub Tasks

Description

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() {
			super.fireStateChanged();
			System.out.println("BANG " + bangCount++);
		}
		private int bangCount = 0;
	}
	class Foo implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			pain.removeTabAt(pain.getSelectedIndex());
			//if you can click the button it's the selected index
		}
	}
	public static void main(String[] args) {
		JTabbedPaneBug jtb = new JTabbedPaneBug();
		jtb.setVisible(true);
	}
}
(Review ID: 85497) 
======================================================================

                                    

Comments
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
    ...
}
======================================================================
                                     
2004-06-11
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.


======================================================================
                                     
2004-06-11
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
tiger

FIXED IN:
tiger

INTEGRATED IN:
tiger
tiger-b03


                                     
2004-06-14



Hardware and Software, Engineered to Work Together