United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-4146858 : Wrong DefaultButton behavior in Windows & Motif L&Fs

Details
Type:
Bug
Submit Date:
1998-06-08
Status:
Resolved
Updated Date:
2001-02-14
Project Name:
JDK
Resolved Date:
2001-02-14
Component:
client-libs
OS:
windows_nt,generic,windows_95
Sub-Component:
javax.swing
CPU:
x86,generic
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.1.6,1.1.7,1.2.0,1.2.2,1.3.0
Fixed Versions:
1.4.0 (beta)

Related Reports
Duplicate:
Duplicate:

Sub Tasks

Description

Name: el35337			Date: 06/08/98


Swing 1.0.2 - JDK 1.1.6 - Win 95/NT - Windows L&F

Try the following example programm.
The first button is the default button. You
can select it with enter.
- press TAB: the default button has the focus. OK
- press TAB again: now the second button has the
  focus and is the default button. OK
- press TAB again: the CheckBox has the focus.
  The second button is the default (see black
  border or try with ENTER). I think this is
  WRONG. The "DefaultButton" should be the
  default Button, again. This is the behaviour
  I see in Windows.

If a component that is not a button is selected
the button set as default button should own the
status "default button". Not the last button which
owned the focus.

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

public class DefaultButton extends JFrame
{
	JButton db = new JButton("DefaultButton");
	JButton ab = new JButton("Button 2");
	JCheckBox cb = new JCheckBox("A Component");
	
	public DefaultButton()
	{
		setTitle("Strange DefaultButton");
		getContentPane().setLayout(new FlowLayout());
		getContentPane().add(db);
		getContentPane().add(ab);
		getContentPane().add(cb);
		getRootPane().setDefaultButton(db);
		pack();
	}

    public static void main(String[] args)
    {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch(Exception ex) {System.out.println(ex);}

		JFrame my = new DefaultButton();
        my.setVisible(true);
    }
}
(Review ID: 33248)
======================================================================

Name: skT88420			Date: 08/06/99


Default Pushbutton behaviour in windows look and feel is much different from the normal windows apps.
Generally , if there is a default pushbutton and some other pushbuttons in a windows app, when focus is on an editfield, the default button will become  the one set initially , and once the focus goes to another pushbutton, it becomes default pushbutton. This is right in the java app too.
But in native windows applications,  when focus goes back to another editfield or some other control other than pushbutton, the default button reverts back to the one which was assigned default initially.
But in JDK1.2 with swing, pushbutton which had last focus still remains default pushbutton even when focus goes to some other edit field.
Steps to reproduce :
1.Cut and Paste the app given to MyDialog.java and compile and run it.
2.Initially focus is on 'First' text area. We can see that the button with text 'Default' is painted as default, Press Enter key , we can see Default button gets activated.
3.Tab to Test1. Default button becomes 'Test 1' which is right behaviour.
4.Tab until Close and then tab again to 'Second' Text area.
See that default button still remains 'Close'
Press Enter key, we can see that the Close button is activated, and makes the window invisible.
Actually, Default button should have got activated instead.
See any of the windows native app and you can see the explained behaviour.
-----------------------------------------------------------------
//Source code

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import javax.swing.border.*;

public class MyDialog extends JDialog implements ActionListener
{
static JFrame parentFrame;
static MyDialog errDialog;

public MyDialog(JFrame parent,
String title,
boolean modal) {
super(parent,title,modal);
setSize(400, 200);

JPanel ButtonArea = new JPanel();

JButton tst1 = new JButton("Test 1");
JButton tst2 = new JButton("Test 2");

JButton def = new JButton("Default");
JButton closeButton = new JButton("Close");

closeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) 
	{
		setVisible(false);
	}
});

def.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
System.out.println("Default Button");
}
});


ButtonArea.add(tst1);
ButtonArea.add(tst2);
ButtonArea.add(def);
ButtonArea.add(closeButton);

JTextField first = new JTextField("First", 20); 
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
Keymap map1 = first.getKeymap();
map1.removeKeyStrokeBinding(enter);

JTextField tf = new JTextField("Second", 20); 
Keymap map2 = tf.getKeymap();
map2.removeKeyStrokeBinding(enter);

getContentPane().setLayout(new FlowLayout());

getContentPane().add(first);
getContentPane().add(ButtonArea);
getContentPane().add(tf);
getRootPane().setDefaultButton(def);

}
	public void actionPerformed(ActionEvent ae) 
	{
		System.out.println("The action command is :"+ae.getActionCommand());
		if(ae.getActionCommand() == "Close")
		{
			setVisible(false);
			dispose();
		}

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

		try
		 {
		 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		 }
		 catch (Exception e)//UnsupportedLookAndFeelException e)
		 {}
		parentFrame = new JFrame();
		parentFrame.setSize(400, 200);
		parentFrame.addWindowListener(new WindowAdapter() { 
		public void windowClosing(WindowEvent e) {
		System.exit(0);
		} // windowClosing
		} ); 

  String title = " My Dislog ";

 MyDialog myDialog = new MyDialog(parentFrame, title, true);
 myDialog.setVisible(true);
}

}
(Review ID: 93605)
======================================================================

Name: skT88420			Date: 08/25/99


JOptionPane.showConfirmDialog(parent,
			msg, title, JOptionPane.YES_NO_OPTION, 
			JOptionPane.QUESTION_MESSAGE);

1.  In WINDOWS Look and feel show the dialog
2.  change the focus to the "No" option.
3.  Press Enter.
4.  'No' option activates which is correct behavior.

5.  In SWING Look and feel show the dialog
6.  change the focus to the "No" option.
7.  Press Enter.
8.  'Yes' option activates even though 'No' has focus.

I believe item 8 is incorrect behavior.
(Review ID: 94376)
======================================================================

Name: skT88420			Date: 02/08/2000


java version "1.3.0rc1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0rc1-T)
Java HotSpot(TM) Client VM (build 1.3.0rc1-S, mixed mode)

Setting the default button on a JRootPane doesn't work when there are multiple
JInternalFrames visible.  When there is only one internal frame, setting
frame.getRootPane().setDefaultButton(button) works as expected.  Attached is
code to demonstrate.  After running the demo, do the following:

1) There are two internal frames stacked on top of each other.  Move the top
one so that you can see the bottom frame.
2) Notice that the bottom frame button has the dark default button border, but
the top frame does not.
3) Pressing enter show trigger the button and change its label to "clicked".
Press enter and notice the top frame does nothing.
4) Now activate the bottom frame and notice the default border around button
goes away.  Press enter to show it does nothing also.

Now recompile the program after commenting out one of the two lines "AddFrame
()" so that only one JInternalFrame is created.  Run it and notice that the
default button works correctly and will change its text when enter is pressed.

Here is the code to demonstrate the problem:

package test;

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

public class DefaultButtonTest extends JFrame implements ActionListener {
	
	JDesktopPane desktop = new JDesktopPane();
	
	public static void main(String[] args) {
		new DefaultButtonTest();
	}
	
	public DefaultButtonTest() {
		getContentPane().add(desktop);
		setSize(500, 300);
		show();

		AddFrame();
		AddFrame();
	}
	
	private void AddFrame() {
		JInternalFrame frame = new JInternalFrame();
		desktop.add(frame);
		JButton button = new JButton("test");
		button.addActionListener(this);
		frame.getRootPane().setDefaultButton(button);
		frame.getContentPane().setLayout(new FlowLayout());
		frame.getContentPane().add(button);
		frame.setSize(300, 200);
		frame.show();
	}
	
	public void actionPerformed(ActionEvent e) {
		((JButton)e.getSource()).setText("clicked");
	}
}
(Review ID: 100980)
======================================================================

Name: jk109818			Date: 06/21/2000


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

Activating and disactivating internal frames removes the default button:

1. Activate top left internal frame by clicking on the title bar
2. Press Enter --> Button is pressed as it should
3. Activate bottom right internal frame by clicking on the title bar
4. Press Enter --> Default button is NOT activated as it should
5. Click again in the title bar of the top left internal frame
6. Press Enter --> Default button is NOT activated as it should

Code that demonstrates the problem:

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

public class DefaultButtonBug
{
	static void addInternalFrame(JDesktopPane desktop, int x, int y)
    {
        final JButton btn = new JButton("Button");
		final JInternalFrame iframe = new JInternalFrame();

        iframe.getContentPane().add(new JTextField(), BorderLayout.NORTH);
        iframe.getContentPane().add(btn, BorderLayout.SOUTH);

		iframe.pack();
        iframe.setLocation(x, y);
		iframe.setSize(100,100);
        iframe.setVisible(true);
		desktop.add(iframe);

        iframe.getRootPane().setDefaultButton(btn);

        // This is the workaround code:
/*		iframe.addInternalFrameListener(new InternalFrameAdapter() {
			public void internalFrameActivated(InternalFrameEvent e)
            {
                iframe.getRootPane().setDefaultButton(btn);
            }
         });
*/
    }

	static public void main(String[] args)
	{
		JFrame frame = new JFrame();
		JDesktopPane desktop = new JDesktopPane();

		frame.setContentPane(desktop);
		frame.pack();
		frame.setSize(400,400);
		frame.setVisible(true);

		addInternalFrame(desktop, 0, 0);
		addInternalFrame(desktop, 200, 200);
	}
}
(Review ID: 105892)
======================================================================

                                    

Comments
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
merlin
merlin-beta

FIXED IN:
merlin-beta

INTEGRATED IN:
merlin-beta


                                     
2004-06-14
WORK AROUND



Name: skT88420			Date: 08/25/99


None
(Review ID: 94376)
======================================================================

Name: skT88420			Date: 02/08/2000


None.  (As usual, don't use Java2)
(Review ID: 100980)
======================================================================
                                     
2004-06-11
EVALUATION

This is true.  HOwever, it's going to be difficult to fix, given the current
organization of the focus/default-handling code.  Currently the defaultbutton-
setting code is contained in the button UI implementation, and from there it
has no way of telling what type of component a button is losing focus to.
I suppose the logic for this handling should really be in the focus manager.

amy.fowler@Eng 1998-09-30

Turns out this is also a problem in the Motif LAF.


I've almost got a fix working, however I really need a reliable way of
detecting generic focus changes that isn't currently possible with
the existing api.  Specifically, the case I need to be able to detect
is when focus leaves a JButton and moves into a non-JButton.
(there are hacks I could use, but cleaning up the api would be preferable)

amy.fowler@Eng 1998-09-30
amy.fowler@Eng 1998-12-11

Still don't have appropriate FocusManager api to fix this in a reasonable
way.  moving the committment to merlin.

amy.fowler@Eng 1999-10-12

I have now fixed this problem by modifying BasicRootPaneUI to store the
original "default" setting and then BasicButtonListener will reset the
default to this value when focus leaves the button.  

amy.fowler@Eng 2001-02-07
                                     
2001-02-07



Hardware and Software, Engineered to Work Together