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

Swing Components in Bean - ActiveX Controlls don't regain focus

XMLWordPrintable

    • x86
    • generic, windows_nt



      Name: sg39081 Date: 12/20/99


      c:\cepheus\classes>java -version
      java version "1.2.2"
      Classic VM (build JDK-1.2.2-001, native threads, symcjit)

      This bug is similiar to Bug Id 4224226 which was closed out
      as not reproducible.

      I'll try to give you enough code to reproduce it.

      Obviously it only appears on Windows machines.

      The bug shows itself when swing components in a bean
      are used as ActiveX components.
      The packager is used to package the beans as ActiveX controls.

      If the 'parent' window of the ActiveX Bean loses the focus
      and regains it (any Dialog will do) the Swing components do
      not get the keyboard focus (though it looks like it.
      The mouse can still be used and a cursor is painted, but no
      keyboard event gets through to the component.

      I tried it different ways. The only way to regain the
      focus is to have at least one awt component on the screen that
      can be activated. After that the swing components are able to
      also get the keyboard focus.

      The example I provide works with Visual Basic 6.0.
      Though I also tried it in Excel and with java dialogs.
      For convenients I wrote a little VB Program that show the
      effect.

      After compiling the java files, building a jar and registering the bean
      you can start the provided VB program.
      A Window will appear. You can enter text into the textfield as you like.
      By pressing the button a MsgBox will appear telling "click".
      After pressing OK on the MsgBox you will not be able
      to enter any more text into the textfield.


      Following is the Code:

      DemoBean.java
      #############
      package demo;

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

      // for packaging (JAR)
      // don't package swing or orb classes with the bean!
      // needed jar (non usual) "jaws.jar" -> sun.beans.ole.OleEmbeddedFrame
      public class DemoBean extends JPanel
      {
      private GridBagLayout gridBagLayout1;
      private JButton loginButton;

      private JTextField nameTextField;

          private transient boolean initiated = false;
      private transient Vector loginListeners;

      public DemoBean()
      {
      try
      {
      jbInit();
      init();
      }
      catch(Exception ex)
      {
      com.isb.service.server.ServerData.printStackTrace(ex);
                  ex.printStackTrace();
      }
      }

      private void jbInit() throws Exception
      {
      gridBagLayout1 = new GridBagLayout();
      loginButton = new JButton();

      nameTextField = new JTextField();
      this.setLayout(gridBagLayout1);
      loginButton.setText("Button");

      nameTextField.setText("Some Text");
      this.add(loginButton, new GridBagConstraints(2, 2, 1, 1, 1.0,
      1.0
                  ,GridBagConstraints.SOUTHEAST, GridBagConstraints.NONE, new
      Insets(0, 0, 0, 0), 0, 0));
      this.add(nameTextField, new GridBagConstraints(0, 0, 1, 1, 0.0,
      0.0
                  ,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new
      Insets(0, 0, 0, 0), 0, 0));
      }

          private void resizeToBeanSize()
          {
              Dimension size = null;
              // this is somewhat stupid...
              // but otherwise the size of the component
              // is not correct
              // (if bean - activeX component is sized differently
              // in the application than of the component used HERE
              // e.g. in visual Basic the components can be sized anyway
              // the 'Designer' likes. The components do not
              // get updated correctly by the OLE Frame...
              // we have to do it ourselfs)

              // get size of upperMost Parent (Bean: sun.beans.ole.OleEmbeddedFrame)
              Container p = getParent();
              while (p != null)
              {
                  if ( p.getClass().equals(sun.beans.ole.OleEmbeddedFrame.class) )
                  {
      size = p.getSize();
                 }
           p = p.getParent();
            }

           if (size != null)
              {
                  p = getParent();
                  // and look for current Parent (Bean: java.awt.Panel)
                  while (p != null)
                  {
                      if ( p.getClass().equals(java.awt.Panel.class) )
                      {
                          p.setSize(size);
                          break;
                      }
                      p = p.getParent();
                  }
              }
          }

      // needed for initializing listeners ...
          public void init() throws Exception
          {
      if (!initiated)
              {
                 // add listeners, since they get 'forgotten' during
                  // serialization...

                 // if loginButton transient
                  // than this causes a NullPointer Exception
                  // in VB
                  // either keep it Serializable or
                  // test and reinstantiate!
                  loginButton.addActionListener(new java.awt.event.ActionListener()
                  {
                      public void actionPerformed(ActionEvent e)
                      {
                          loginButton_actionPerformed(e);
                      }
                  });

                  // and set correct beansize to this panel!
                  initiated = true;
      }
                  resizeToBeanSize();
          }

      public synchronized void removeLoginListener(LoginListener l)
      {
      if (loginListeners != null && loginListeners.contains(l))
      {
      Vector v = (Vector) loginListeners.clone();
      v.removeElement(l);
      loginListeners = v;
      }
      }

      public synchronized void addLoginListener(LoginListener l)
      {
      Vector v = loginListeners == null ? new Vector(2) : (Vector)loginListeners.clone();
      if (!v.contains(l))
      {
      v.addElement(l);
      loginListeners = v;
      }
      }

      protected void fireLogin(LoginEvent e)
      {
      if(loginListeners != null)
      {
      Vector listeners = loginListeners;
      int count = listeners.size();
      for (int i = 0; i < count; i++)
      {
      ((LoginListener)listeners.elementAt(i)).login(e);
      }
      }
      }

      private void loginButton_actionPerformed(ActionEvent e)
      {
      fireLogin(new LoginEvent(this));
      }

      }

      DemoBeanBeanInfo.java
      #####################
      package demo;

      import java.beans.*;

      public class DemoBeanBeanInfo extends SimpleBeanInfo
      {
      Class beanClass = DemoBean.class;
      String iconColor16x16Filename;
      String iconColor32x32Filename;
      String iconMono16x16Filename;
      String iconMono32x32Filename;

      public DemoBeanBeanInfo()
      {
      }

      public MethodDescriptor[] getMethodDescriptors()
          {
         try
         {
      Class[] params1 = new Class[0];
      java.lang.reflect.Method _initMethod =beanClass.getMethod("init", params1);
             MethodDescriptor _initDescription = new MethodDescriptor(_initMethod);

                  MethodDescriptor[] mds = new MethodDescriptor[] {
                          _initDescription,
                          };
                  return mds;
           }
      catch(NoSuchMethodException ex)
      {
      ex.printStackTrace();
      return null;
      }
      }

      public PropertyDescriptor[] getPropertyDescriptors()
      {
      PropertyDescriptor[] pds = new PropertyDescriptor[] { };
      return pds;
      }

      public java.awt.Image getIcon(int iconKind)
      {
      switch (iconKind) {
      case BeanInfo.ICON_COLOR_16x16:
      return iconColor16x16Filename != null ?loadImage(iconColor16x16Filename) : null;
      case BeanInfo.ICON_COLOR_32x32:
      return iconColor32x32Filename != null ?loadImage(iconColor32x32Filename) : null;
      case BeanInfo.ICON_MONO_16x16:
      return iconMono16x16Filename != null ?loadImage(iconMono16x16Filename) : null;
      case BeanInfo.ICON_MONO_32x32:
      return iconMono32x32Filename != null ?loadImage(iconMono32x32Filename) : null;
      }
      return null;
      }
      }

      LoginEvent.java
      ###############
      package demo;

      import java.util.*;

      public class LoginEvent extends EventObject
      {
      public LoginEvent(Object source)
      {
      super(source);
      }
      }

      LoginListener.java
      ##################
      package demo;

      import java.util.*;

      public interface LoginListener extends EventListener
      {
      public void login(LoginEvent e);
      }

      DemoBean.mf
      ###########
      Manifest-Version: 1.0

      Name: demo/DemoBean.class
      Java-Bean: True

      Name: demo/DemoBeanBeanInfo.class

      demo.bat (location dependent)
      ########
      jar.exe -cfm demo.jar .\DemoBean.mf -C \classes demo
      rem register bean to ActiveX
      java -classpath %CLASSPATH% sun.beans.ole.Packager -jar .\demo.jar -n
      demo.DemoBean -ax DemoBean -o c:\Programme\JavaSoft\Jre\1.2\classes


      demo.vbp
      ########
      Type=Exe
      Form=Demo.frm
      Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\WINNT40W\syst
      em32\Stdole2.tlb#OLE Automation
      Object={74D204D1-B45A-11D3-8D76-00105A31118A}#1.0#0; beans.ocx
      Startup="Form1"
      Command32=""
      Name="Projekt1"
      HelpContextID="0"
      CompatibleMode="0"
      MajorVer=1
      MinorVer=0
      RevisionVer=0
      AutoIncrementVer=0
      ServerSupportFiles=0
      VersionCompanyName="Software AG"
      CompilationType=0
      OptimizationType=0
      FavorPentiumPro(tm)=0
      CodeViewDebugInfo=0
      NoAliasing=0
      BoundsCheck=0
      OverflowCheck=0
      FlPointCheck=0
      FDIVCheck=0
      UnroundedFP=0
      StartMode=0
      Unattended=0
      Retained=0
      ThreadPerObject=0
      MaxNumberOfThreads=1

      demo.frm
      ########
      VERSION 5.00
      Object = "{74D204D1-B45A-11D3-8D76-00105A31118A}#1.0#0"; "beans.ocx"
      Begin VB.Form Form1
         Caption = "Form1"
         ClientHeight = 3195
         ClientLeft = 60
         ClientTop = 345
         ClientWidth = 4680
         LinkTopic = "Form1"
         ScaleHeight = 3195
         ScaleWidth = 4680
         StartUpPosition = 3 'Windows-Standard
         Begin DemoBeanCtl.DemoBean DemoBean1
            Height = 1215
            Left = 480
            Top = 600
            Width = 2535
         End
      End
      Attribute VB_Name = "Form1"
      Attribute VB_GlobalNameSpace = False
      Attribute VB_Creatable = False
      Attribute VB_PredeclaredId = True
      Attribute VB_Exposed = False

      Private Sub DemoBean1_Login(ByVal ComponentEvent1 As Object)
          MsgBox ("Click")
      End Sub

      Private Sub Form_Load()
          DemoBean1.init
          
      End Sub

      demo.vbw
      ########
      Form1 = 44, 44, 494, 530, , 22, 22, 472, 508, C
      (Review ID: 99134)
      ======================================================================

      Name: boT120536 Date: 06/03/2001


      java version "1.4.0-beta"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta-b65)
      Java HotSpot(TM) Client VM (build 1.4.0-beta-b65, mixed mode)


      STEPS TO REPRODUCE

      1. Create a very simple bean that is a JPanel containing a JTextField.
      2. In Microsoft Visual Basic 6.0, do File -> New Project -> Standard Exe, add
      the bean component to the blank form, compile and run.
      3. No caret in the JTextField. No focus possible in the JTextField.

      JAVA SOURCE CODE TO REPRODUCE

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

      public class AXBeanBug extends JPanel implements Serializable {

        public AXBeanBug() {
          add(new JTextField("Some sample text"));
        }

      }


      Manifest file:

      Name: AXBeanBug.class
      Java-Bean: True


      OTHER
      This is the simplest reproduction of the problem I could find.
      The product bean I have developed where the problem first arose has a much more
      complex interface and has been necessary to ship to customers as an Java
      application in JDK1.3 because of focus problems in that release. Pre-release
      buzz on 1.4 seemed to suggest that it might solve the focus problems but not so
      far. My company wishes to ship the bean with a VB API so developers in VB
      environments can absorb it into their applications but this will not be
      possible unless the focus problems are fixed. We seen the VB API as a
      significant additional revenue stream for our product.
      (Review ID: 125137)
      ======================================================================

            asultano Alex Sultanov
            sgoodsunw Sheri Good (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: