Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4136561
Votes 1
Synopsis JTabbedPane handling of duplicate child components
Category java:classes_swing
Reported Against swing1.0.2
Release Fixed
State 11-Closed, Will Not Fix, bug
Priority: 4-Low
Related Bugs
Submit Date 08-MAY-1998
Description




Swing 0.7 supported multiple tabs with the same
component and exhibited perfect behavior in that
respect. Swing 1.0.1 basically worked too, though
it introduced a layout problem on resize.

However, Swing 1.0.2 completely breaks this ability.
When multiple tabs are attached to the same component,
the behavior is completely wrong: missing tabs; the
component doesn't display, etc.

What is surprising is how small the code changes are
between 1.0.1 and 1.0.2 for JTabbedPane.  Below is a
test snippet that demonstrates how dramatically different
those changes behave.

Before that, you might ask "why would one want to do this?"
Well, we add a custom SingleSelectionModel to the JTabbedPane
that is linked to a network of data models driving sub-components
within a single JPanel that is added to all tabs.
Essentially, the tabs serve as a radio button with a
variant rendering (as they should have been originally
architected, IMHO).
Within the world of MVC, this should be a completely
legitimate use of JTabbedPane.

Here's the tester:

<PRE><TT>
import com.sun.java.swing.*;
import java.awt.*;
import com.sun.java.swing.JFrame;

import com.sun.java.swing.JTabbedPane;
import com.sun.java.swing.JLabel;
public class TabTester extends com.sun.java.swing.JFrame
{
	public TabTester()
	{
		getContentPane().setLayout(new BorderLayout(0,0));
		setVisible(false);
		setSize(405,305);
		
		jTabbedPane1 = new com.sun.java.swing.JTabbedPane();
		getContentPane().add(jTabbedPane1);
		
		jLabel1 = new com.sun.java.swing.JLabel("Label 1");
		jTabbedPane1.addTab("First=1", null, jLabel1, null);
		
		jLabel2 = new com.sun.java.swing.JLabel("Label 2");
		jTabbedPane1.addTab("Second=2", null, jLabel2, null);
		
		jTabbedPane1.addTab("Third=1", null, jLabel1, null);
        jTabbedPane1.addTab("Fourth=2", null, jLabel2, null);
        
		SymWindow aSymWindow = new SymWindow();
		this.addWindowListener(aSymWindow);
	}

	public TabTester(String sTitle)
	{
		this();
		setTitle(sTitle);
	}

	public void setVisible(boolean b)
	{
		if (b)
			setLocation(50, 50);
		super.setVisible(b);
	}

	static public void main(String args[])
	{
		(new TabTester()).setVisible(true);
	}

	com.sun.java.swing.JTabbedPane jTabbedPane1;
	com.sun.java.swing.JLabel jLabel1;
	com.sun.java.swing.JLabel jLabel2;

	class SymWindow extends java.awt.event.WindowAdapter
	{
		public void windowClosing(java.awt.event.WindowEvent event)
		{
			Object object = event.getSource();
			if (object == TabTester.this)
				TabTester_WindowClosing(event);
		}
	}

	void TabTester_WindowClosing(java.awt.event.WindowEvent event)
	{
		setVisible(false); // hide the Frame
		dispose();	     // free the system resources
		System.exit(0);    // close the application
	}
}
</TT></PRE>

- JJ
(Review ID: 29924)
======================================================================
Work Around
The program below shows how to "fake" a TabbedPane into displaying
a single component for all tabs.
==============================================================================

import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;
import com.sun.java.swing.event.*;


public class TabShare extends JFrame {

    public TabShare() {
        super("TabShare Test");

        JTabbedPane tabPane = new JTabbedPane();

        // Make the "always visible" panel the first child so
        // that it always remains "on top" of the z-order
        AlwaysShowingPanel panel = new AlwaysShowingPanel();
        tabPane.addChangeListener(panel);
        tabPane.addComponentListener(panel);
        tabPane.add("One", panel);

        tabPane.add("Two", new JLabel("dummy"));
        tabPane.add("Three", new JLabel("dummy"));
        tabPane.add("Four", new JLabel("dummy"));

        getContentPane().add(tabPane, BorderLayout.CENTER);
        pack();
    }
    public static void main(String[] args) {
        TabShare test = new TabShare();
        test.setVisible(true);
    }
}

class AlwaysShowingPanel extends JPanel implements ChangeListener, ComponentListener {

    private String message = "";
    private boolean red = true;

    public Dimension getPreferredSize() {
        return new Dimension(200,100);
    }

    public void paintComponent(Graphics g) {
        Dimension size = getSize();

        if (red) {
            g.setColor(Color.red);
            red = false;
        } else {
            g.setColor(Color.white);
            red = true;
        }
        g.fillRect(0, 0, size.width-1, size.height-1);
        g.setColor(Color.black);
        g.drawString("Pretending to be Tab "+message, 20, 50);
    }


    public void setVisible(boolean visible) {
        // do nothing - we want to always be visible!
    }

    /* Change Listener */
    public void stateChanged(ChangeEvent e) {
        JTabbedPane tabPane = (JTabbedPane)e.getSource();
        message = tabPane.getTitleAt(tabPane.getSelectedIndex());
    }

    /* Component Listener */
    public void componentResized(ComponentEvent e) {
       
        // Since the TabbedPane only resizes the child it thinks is
        // the selected tab, we must track size changes ourself and
        // resize to the currently selected tab component's size
        //
        JTabbedPane tabPane = (JTabbedPane)e.getSource();
        Component selected = tabPane.getComponentAt(tabPane.getSelectedIndex());
        setSize(selected.getSize());
        validate();
    }
    public void componentMoved(ComponentEvent e) {}
    public void componentShown(ComponentEvent e) {}
    public void componentHidden(ComponentEvent e) {}
}
Evaluation
In 1.0.2, we changed the TabbedPane to use visibility instead of containment for
display of the currently selected tab (we did this to support builders,
who couldn't deal with it the  xxxxx  way).  This indeed would break code
which tried to use the same component for all tabs, however since this
behavior wasn't officially spec'd, this is not really a bug.

The good news is that there IS a workaround to do what you wish. 
See sample program in Workaround section.

 xxxxx@xxxxx  1998-06-02
Comments
  
  Include a link with my name & email   


PLEASE NOTE: JDK6 is formerly known as Project Mustang