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: 4177727
Votes 32
Synopsis propagating disEnabled "event" to all children
Category java:classes_awt
Reported Against 1.2 , 1.1.7 , 1.2.2 , 1.2beta4 , kestrel-beta
Release Fixed
State 6-Fix Understood, request for enhancement
Priority: 4-Low
Related Bugs 4224470 , 4248716 , 4300028 , 4301871
Submit Date 30-SEP-1998
Description


The JTabbedPane and JPanel can contain many components
as children.  When the method setEnabled(false) is
called on the containers, the children of these
containers should be disabled as well.
(Review ID: 39637)
======================================================================




Calling the setEnabled method on any swing component does not 
disable/enable any of the chilren components of the parent.  
For example, if a JPanel contains a JButton, calling 
setEnabled(false) on the JPanel does not disable the JButton, 
but disables only the JPanel.  In awt, this method not only 
disables the Panel but any children components, which is the
expected behavior.
(Review ID: 94027)
======================================================================




Classic VM (build JDK-1.2.2-U, native threads, symcjit)


As explained in the report for Bug 1257395, containers do not recursively
invoke enable/disable on their children.  This results in a strange visual
appearance where components that are not active look like they are active.  I
believe this should be a platform independent problem, but I have given the
details of the particular setup I am using.  The code given below demonstrates
the issue and, by adding one line, can be made to show what I feel is the
correct behavior.  Although the bug is closed, the problem still exists, even
in the VM's that supposedly contain the fix.

Note that the problem is a visual one.  The children (in this case a button)
are in fact inactive.  However, they look the same as enable components.  On
the other hand, if containers were to recursively invoke disable on their
children, the correct visual cue would be given that the button is disabled.

// Testing whether Sun Bug 1257395 has been fixed (as reported).
// The bug is that containers do not recursively enable and disable
// their children.

import java.awt.*;
import java.awt.event.*;

public class Test extends Frame {
  public Test (String title) {
    super(title);
    init();
  }

  public void init () {
    addWindowListener(new WindowAdapter() {
      public void windowClosing (WindowEvent e) { System.exit(0); }
    });

    final JButton button = new JButton("Push Me!");
    button.addActionListener(new ActionListener() {
      public void actionPerformed (ActionEvent e) {
	// add the line below to see the difference between recursively
	// disabling all children vs. not doing so.
//  	button.setEnabled(!isEnabled());
	setEnabled(!isEnabled());
      }
    });

    add(button, BorderLayout.CENTER);
    pack();
    setVisible(true);
  }

  public static void main (String[] args) {
    new Test();
  }
}

------------

email from user 11/21/99:

You might want to consider (if it's possible), changing the category of
that bug (4177727) to AWT rather than Swing.  The problem appears more
often with the Swing classes, because it's worse when the container is a
lightweight component (ala JPanel), but it isn't really a Swing bug.
Fixing the problem in Swing would still leave an unresolved issue with
any other lightweight container.

I would add that with a slightly modified test case, the problem is not
limited to the visual appearance.  As I mentioned above, if the
container is a lightweight component, then the children are not disabled
at all (either visually or functionally).  I have included a new version
of my original test program which demonstrates this (and fixes a couple
of minor bugs that I had introduced while reducing the code size for
inclusion in my report).

As for your real question, yes, it would be fine if you added my
comments to the existing bug report rather than opening a new,
independent bug.


(Review ID: 98108)
======================================================================




C:\WINDOWS>java -version
java version "1.2.2"
Classic VM (build JDK-1.2.2-001, native threads, symcjit)


JMenuBar mbar = getJMenuBar();

mbar.setEnabled( !bShow); // Doesn't work! Menu bar is not disabled.

// but the following works
for ( int i = 0; i < mbar.getMenuCount(); i++ )
{
   mbar.getMenu(i).setEnabled( !bShow);
}

Comment to bug ID#4177732 implies this is not a bug and is, in fact,
known behavior of all JComponents.
However, one would be hard-pressed to find this "known" behavior documented,
whether in online documentation or in several advanced books on Swing.
(Review ID: 99343)
======================================================================
Posted Date : 2006-01-16 16:25:13.0
Work Around


Override the JTabbedPane and JPanel's setEnabled()
method.  And disabled their children when that method
is called
======================================================================




the only workaround would be to extend every swing component
that extends JComponent and over-ride the setEnabled method. In
that method call the setEnabled method of every child component.

ex:
public void setEnabled(boolean enabled) {
   super.setEnabled(enabled);
   Component[] components = getComponents();
   if (components != null && components.length > 0) {
      int count = components.length;
      for (int i = 0; i < count; i++)
         components[i].setEnabled(enabled);
   }
}
(Review ID: 94027)
======================================================================




Write a utility function that calls enable/disable on a container's children.
Use that function instead of the method.
(Review ID: 98108)
======================================================================
Evaluation
This is definitely a hole in the toolkit.  disabling a container should automatically
disable it's descendents, but it doesn't currently work that way, which
requires programs to write lots of tree traversal code.

We developing a proposal to fix this for merlin.

  xxxxx@xxxxx   2000-03-09

As change of this scope would likely make more sense in awt, and then Swing would just pick it up.
  xxxxx@xxxxx   2001-10-09
Contribution-Forum:https://jdk-collaboration.dev.java.net/servlets/ProjectForumMessageView?messageID=11928&forumID=1463
Posted Date : 2006-03-10 23:06:28.0
Comments
  
  Include a link with my name & email   

Submitted On 27-OCT-1998
gmarch
When this is fixed, make sure that when setEnabled(true)
is called, that the children are returned to their
original state which may be true or false.


Submitted On 31-DEC-1998
nateF
lack of recursive behavior for setEnabled isn't so bad as the lack of a note in
the API documentaion clarifying this point


Submitted On 17-AUG-1999
kamalkalra
how can this bug be in evaluation mode since sep 1998?


Submitted On 13-JUL-2000
dmpotter
Can't this be fixed with a simple edit to the basic java.lang.Container class?  Add a setEnabled() function to 
lock the tree and then get the components and call their setEnabled() functions.  IE,

public void setEnabled(boolean enable) {
    super.setEnabled(enable);
    synchronized(getTreeLock()) {
        Component comps[] = getComponents();
        for(int i = 0; i &lt; comps.length; i++)
            comps[i].setEnabled(false);
    }
}

Or maybe add a private function to traverse the tree, so that setEnabled(), disable(), and enable() can all 
call that method to prevent infinite recursion when java.lang.Component's setEnabled() function calls the 
deprecated disable() and enable() functions.


Submitted On 17-AUG-2000
vas
Note that when this is fixed, setting a Container with a 
Border (such as a JPanel with a Border), the border should 
be &quot;greyed out&quot; to indicate that the panel is disabled.


Submitted On 09-NOV-2000
mikewse
Make sure to look at the way this is solved in the 
X Windows / Xt Intrinsics toolkit. They have an
elegant way of solving how to restore childrens'
states when doing setEnabled(true) on the parent.
Roughly it works like this:
They use a sensitive/ancestor_sensitive technique
so that the child stores its own setting for
&quot;enabled&quot; which is not modified by the parent.
BUT when the child makes its decision about whether
it is actually enabled it ANDs its own setting
with its parent's setting.


Submitted On 21-MAR-2001
steven_lunt
should work like the visible property.  isVisible() returns 
the property of this component only.  isShowing() returns 
isVisible() &amp;&amp; (parent == null || parent.isShowing())


Submitted On 21-MAR-2001
steven_lunt
see bug 4251567



PLEASE NOTE: JDK6 is formerly known as Project Mustang