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

When removing a JPanel, child JButton gets a FOCUS_GAINED

XMLWordPrintable

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

      Name: rmT116609 Date: 05/20/2003


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

      (Note this bug was also present in 1.4.1.)

      FULL OS VERSION :
      Microsoft Windows 2000 [Version 5.00.2195]

      A DESCRIPTION OF THE PROBLEM :
      Applet contains a JPanel that has several child components, one of which has the focus. Removal of that JPanel (from the JApplet) causes a FOCUS_GAINED event for another child component of that JPanel (the same JPanel which is being removed). Focus remains on that removed component.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1.Run the applet
      2.Mouse-click the first button
      3.Watch the Java console output
      4.Notice that second button gets the focus (and keeps it) after it has been removed.


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      I expect the focus to be either:
      1. Lost to all components of the applet
      or
      2. Gained by some Applet component that is still displayable.
      ACTUAL -
      Java console shows that after the panel is removed, the second button of that panel (which is no longer displayable) gets a FOCUS_GAINED event. The focus stays there (as long as you don't click away from the applet, e.g. to activate the console window).


      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      Console output after clicking first button:
      removing old panel
      adding new panel
      FOCUS_LOST by 1
      FOCUS_GAINED by 2

      (Note if you see a final "FOCUS_LOST by 2", it is because you clicked away from the applet -- don't do that.)

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      // JApplet1.java
      // Demonstrates FOCUS_GAINED bug.

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

      public class JApplet1 extends JApplet implements FocusListener, ActionListener
      {
        private int nextBtnNum = 1;
        private JPanel curPanel;
        private JButton curBtns[];

        public void init()
        {
          getContentPane().setLayout(new BorderLayout(0,0));
          setSize(400,100);

          createCurPanel();
          getContentPane().add(BorderLayout.CENTER, curPanel);
          curBtns[0].requestFocus();
        }

        // Create a 3-button panel into the "curPanel" variable.
        private void createCurPanel()
        {
          curPanel = new JPanel();
          curPanel.setFocusCycleRoot(true);
          curPanel.setFocusTraversalPolicy(new ContainerOrderFocusTraversalPolicy());
          curPanel.addFocusListener(this);

          curBtns = new JButton[3];
          curPanel.setLayout(new FlowLayout(FlowLayout.CENTER,5,5));
          for (int m=0; m < 3; m++) {
            JButton btn = new JButton(String.valueOf(nextBtnNum++));
            curPanel.add(btn);
            btn.addActionListener(this);
            btn.addFocusListener(this);
            curBtns[m] = btn;
          }
        }

        // Replace curPanel by a new 3-button panel
        private void replacePanel()
        {
          System.out.println("removing old panel");
          getContentPane().remove(curPanel);
          createCurPanel();
          System.out.println("adding new panel");
          getContentPane().add(BorderLayout.CENTER, curPanel);
          validate();

          // If we don't do a requestFocus here, the focus will be left
          // on one of the buttons of the panel that was removed.

          // If we want the focus to go to the new panel, we have to do
          // the following:
          //SwingUtilities.invokeLater(
          // new Runnable() { public void run() { curBtns[0].requestFocus(); }});

          // Simply calling
          // curBtns[0].requestFocus();
          // here doesn't work. Is this another bug?
        }

        private String describeComponent(Component c)
        {
          if (c instanceof JButton) return ((JButton)c).getText();
          if (c == curPanel) return "curPanel";
          return c.toString();
        }

        public void focusGained(FocusEvent e)
        {
          System.out.println("FOCUS_GAINED by " + describeComponent(e.getComponent()));
        }

        public void focusLost(FocusEvent e)
        {
          System.out.println("FOCUS_LOST by " + describeComponent(e.getComponent()));
        }

        // Get button clicks
        public void actionPerformed(ActionEvent e)
        {
          replacePanel();
        }
      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      I made my own FocusTraversalPolicy that returns null from getComponentAfter for a component that I know I am about to remove. This involves marking every component that I am about to remove. This workaround is only a stopgap and we are anxiously awaiting a bug fix.
      (Review ID: 185858)
      ======================================================================

            son Oleg Sukhodolsky (Inactive)
            rmandalasunw Ranjith Mandala (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: