Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4890245

CardLayout lays out cards visibly

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 1.4.2
    • client-libs
    • x86
    • windows_2000



      Name: gm110360 Date: 07/14/2003


      FULL PRODUCT VERSION :
      java version "1.4.1-rc"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-rc-b19)
      Java HotSpot(TM) Client VM (build 1.4.1-rc-b19, mixed mode)

      On Zaurus:
      Insignia Jeode 1.10.2 (Personal Java 1.2)

      FULL OPERATING SYSTEM VERSION :
      Microsoft Windows 2000 [Version 5.00.2195]

      ADDITIONAL OPERATING SYSTEMS :
      Sharp Zaurus with linux 2.4.6-rmk1-np2-embedix (ROM 2.37)


      A DESCRIPTION OF THE PROBLEM :
      [1] When a CardLayout is requested to lay out (for instance
      with a pack() call), it obtains its preferred size from its
      cards and lays out the first visible card.
      But it also lays out the invisible cards with an invalid
      container with a size of 0x0.
      1) This call is not necessary because the preferred size is
      already known.
      2) Not knowing the display size of the card makes some
      layout manager unable to prepare laying out the components.

      [2] When an invisible card becomes visible (call to
      layout.show("card", this)), the call to lay out its
      component is done after the card has been visible.
      1) If the layout manager was not able to anticipate the
      layout of the component (see [1].2), it has to do it again.
      2) This operation is *visible* to the user on slow devices:
      you see the components of the card changing position.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Run the test program
      java -cp . TestCardLayout


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      The test program creates a frame that has a CardLayout with
      two cards. It displays the first card for 4s, then the next
      card for 4s and exits.

      The test program uses instrumented Layout managers and
      components to trace how CardLayout behaves.

      It shows that when the frame is displayed first, both cards
      are requested to layout: the invisible one with an invalid
      container size.

      Then when the second card becomes visible, it lays out its
      components *after* beeing visible.


      I expected:
      - First, only the visible card is laid out: no need to lay
      out the invisible one.
      - When the invisible becomes visible, a request to layout
      its component is done before being visible.


      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      C:\Development\Zepo\src>java -cp . TestCardLayout

      TestPanel:panel2.setVisible(false)

      TestGridLayout.preferredLayoutSize(TestPanel[panel0,0,0,0x0,invalid,layout=TestG
      ridLayout])=java.awt.Dimension[width=230,height=46]

      TestGridLayout.preferredLayoutSize(TestPanel[panel1,0,0,0x0,invalid,hidden,layou
      t=TestGridLayout])=java.awt.Dimension[width=230,height=69]

      TestGridLayout.layoutContainer(TestPanel[panel0,4,23,230x69,invalid,layout=TestG
      ridLayout])
      java.lang.Throwable
              at TestGridLayout.layoutContainer(TestCardLayout.java:100)
              at java.awt.Container.layout(Container.java:1017)
              at java.awt.Container.doLayout(Container.java:1007)
              at java.awt.Container.validateTree(Container.java:1089)
              at java.awt.Container.validateTree(Container.java:1096)
              at java.awt.Container.validate(Container.java:1064)
              at java.awt.Window.pack(Window.java:433)
              at TestCardLayout.<init>(TestCardLayout.java:39)
              at TestCardLayout.main(TestCardLayout.java:51)

      TestGridLayout.layoutContainer(TestPanel[panel1,0,0,0x0,invalid,hidden,layout=Te
      stGridLayout])
      *** ==> The second card is requested to layout without knowing its size!
      java.lang.Throwable
              at TestGridLayout.layoutContainer(TestCardLayout.java:100)
              at java.awt.Container.layout(Container.java:1017)
              at java.awt.Container.doLayout(Container.java:1007)
              at java.awt.Container.validateTree(Container.java:1089)
              at java.awt.Container.validateTree(Container.java:1096)
              at java.awt.Container.validate(Container.java:1064)
              at java.awt.Window.pack(Window.java:433)
              at TestCardLayout.<init>(TestCardLayout.java:39)
              at TestCardLayout.main(TestCardLayout.java:51)

      Showing next pane


      TestPanel:panel1.setVisible(false)

      TestPanel:panel2.setVisible(true)
      *** ==> Now the second card is visible when the container is requested to
      layout again: the user can see the components moving...

      TestGridLayout.layoutContainer(TestPanel[panel1,4,23,230x69,invalid,layout=TestG
      ridLayout])
      java.lang.Throwable
              at TestGridLayout.layoutContainer(TestCardLayout.java:100)
              at java.awt.Container.layout(Container.java:1017)
              at java.awt.Container.doLayout(Container.java:1007)
              at java.awt.Container.validateTree(Container.java:1089)
              at java.awt.Container.validateTree(Container.java:1096)
              at java.awt.Container.validate(Container.java:1064)
              at java.awt.CardLayout.show(CardLayout.java:465)
              at java.awt.CardLayout.last(CardLayout.java:429)
              at TestCardLayout.main(TestCardLayout.java:62)


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------

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

      /**
       * Test how a CardLayout lays out its cards.
       *
       * @author GenePi
       * @created 26 septembre 2002
       */
      public class TestCardLayout
      extends Frame
      {
      /**
      * Create a frame with a CardLayout containing 2 panes.
      */
      TestCardLayout()
      {
      setLayout(new CardLayout());

      Panel panel1 = new TestPanel(new TestGridLayout(0,
      2), "panel1");
      panel1.add(new Label("panel1.label1"));
      panel1.add(new TextField("panel1.field1"));
      panel1.add(new Label("panel1.label2"));
      panel1.add(new TextField("panel1.field2"));

      add(panel1, "panel1");

      Panel panel2 = new TestPanel(new TestGridLayout(0,
      2), "panel2");
      panel2.add(new Label("panel2.label1"));
      panel2.add(new TextField("panel2.field1"));
      panel2.add(new Label("panel2.label2"));
      panel2.add(new TextField("panel2.field2"));
      panel2.add(new Label("panel2.label3"));
      panel2.add(new TextField("panel2.field3"));

      add(panel2, "panel2");

      pack();
      }


      /**
      * The main program for the TestCardLayout. Display the frame for 4s
      with the
      * first pane, then shows the other one for 4s and exits.
      *
      * @param args The command line arguments
      */
      public static void main(final String[] args)
      {
      TestCardLayout win = new TestCardLayout();
      win.show();
      try
      {
      Thread.sleep(4000L);
      }
      catch (InterruptedException ie)
      {
      }
      System.err.println("\nShowing next pane\n");
      CardLayout layout = (CardLayout) win.getLayout();
      layout.last(win);
      try
      {
      Thread.sleep(4000L);
      }
      catch (InterruptedException ie)
      {
      }
      System.exit(0);
      }
      }

      /**
       * Instrumented GridLayout class that prints calls to layoutContainer method.
       */
      class TestGridLayout
      extends GridLayout
      {
      /**
      * Create the layout manager
      *
      * @param row Number of rows
      * @param col Number of columns
      */
      TestGridLayout(final int row, final int col)
      {
      super(row, col);
      }


      /**
      * Print the state of the parent container and the call stack.
      *
      * @param parent The parent container.
      */
      public void layoutContainer(final Container parent)
      {
      System.err.println("\nTestGridLayout.layoutContainer(" + parent
      + ")");
      new Throwable().printStackTrace();
      super.layoutContainer(parent);
      }

      /**
      * Print the preferred size of the layout.
      *
      * @param parent The parent container
      */
      public Dimension preferredLayoutSize(final Container parent)
      {
      System.err.print("\nTestGridLayout.preferredLayoutSize(" +
      parent + ")=");
      Dimension dim = super.preferredLayoutSize(parent);
      System.err.println(dim);
      return dim;
      }
      }

      /**
       * An instrumented panel to know its visibility state.
       */
      class TestPanel
      extends Panel
      {
      // Identifier of the panel
      private String _id;


      /**
      * Create the panel.
      *
      * @param layout The layout manager
      * @param id The identifier of the panel
      */
      TestPanel(final LayoutManager layout, final String id)
      {
      super(layout);
      _id = id;
      }


      /**
      * Displays the visibility of the panel.
      *
      * @param visible The new Visible value
      */
      public void setVisible(final boolean visible)
      {
      System.err.println("\nTestPanel:" + _id + ".setVisible(" +
      visible + ")");
      super.setVisible(visible);
      }
      }

      ---------- END SOURCE ----------

      CUSTOMER WORKAROUND :
      Use extended layout managers and override method
      layoutContainer to check the size of the parent container.

      public void layoutContainer(final Container parent)
      {
      Dimension dim = parent.getSize();
      if (dim.width == 0 && dim.height == 0)
      {
      return;
      }
      super.layoutContainer(parent);
      }
      (Incident Review ID: 165019)
      ======================================================================

            son Oleg Sukhodolsky (Inactive)
            gmanwanisunw Girish Manwani (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: