JDK-4384407 : Default Button problems in Metal and Window LAF
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_nt
  • CPU: x86
  • Submitted: 2000-10-31
  • Updated: 2001-02-10
  • Resolved: 2001-02-10
Related Reports
Duplicate :  
Description
java version 1.4.0beta-b36 on Win 32.

There are a lot of problems with the default button behaviour that was specified with JRootPane.setDefaultButton(JButton) such that pressing the ENTER key will eventually invoke an action event on that button.

1. All Look and Feels: default button doens't render the button pressed action. When the focus is on a non-button or text component (i.e., JCheckBox) then pressing ENTER will route the actionPerformed to the default button but the UI will not paint the button pressed. This is a regression from 1.3.0 and it has been in Merlin since about b26 (Aug 2, 2000).

2. Windows and Motif LAF: The default button changes to the last button that had the focus. Since this is in both these LAFs, then the problem may lie in the plaf.basic package. This may be a feature but JDK 1.2.2 behaves the same way as well. To reproduce forward traverse within the SwingButton test until the focus is on the JCheckBox. Press enter. Notice that the default button is Button 3. If you reverse traverse with shift-tab to the JCheckBox, then Button 1 will be the default.

>>> SwingButton.javaimport javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class SwingButton extends JFrame implements KeyListener, ActionListener {

    // Actions defined for the application
    private WindowsLAF winAction;
    private MotifLAF motifAction;
    private MetalLAF metalAction;

    JButton b1,b2,b3;
    TextField text1;

    public static void main(String args[]){
	SwingButton sb=new SwingButton();
    }

    public SwingButton(){
        super("Super Combo Box Test Shell");
        initActions();
        
        setJMenuBar(createMenu());

	getContentPane().setLayout(new BorderLayout());
	JPanel panel = new JPanel();
	b1=new JButton("Button1");
	panel.add(b1);
	b1.addKeyListener(this);
	b1.addActionListener(this);

	b2=new JButton("Button2");
	panel.add(b2);
	b2.addKeyListener(this);
	b2.addActionListener(this);

	b3=new JButton("Button3");
	panel.add(b3);
	b3.addKeyListener(this);
	b3.addActionListener(this);

	text1=new TextField(10);
	panel.add(text1);
	getContentPane().add(panel, BorderLayout.CENTER);
	getContentPane().add(new JCheckBox("Foo"), BorderLayout.SOUTH);
	getRootPane().setDefaultButton(b2);

	System.out.println("Is Button2 is the Default Button? " + b2.isDefaultButton());

	setSize(300,200);
	setVisible(true);
    }

    // Creates the application menu bar.
    private JMenuBar createMenu()  {
        JMenuBar menuBar = new JMenuBar();

        JMenuItem menuItem;

        // Build the Look and Feel menu        
        JMenu lafMenu = new JMenu("Look and Feel");
        lafMenu.setMnemonic('L');
        menuItem = lafMenu.add(winAction);
        menuItem = lafMenu.add(motifAction);
        menuItem = lafMenu.add(metalAction);

        menuBar.add(lafMenu);
        
        return menuBar;
    }

    private void initActions()  {
        winAction = new WindowsLAF();
        motifAction = new MotifLAF();
        metalAction = new MetalLAF();
    }

    public void actionPerformed(ActionEvent evt) {
	JButton button = (JButton)evt.getSource();
	System.out.print("Button Pressed: " + button.getText());
	if (button.isDefaultButton()) {
	    System.out.println(" is the default button");
	} else {
	    System.out.println("");
	}
	    
    }

    public void keyPressed(KeyEvent event){
	if (event.getSource() == b1)
	    text1.setText("Button1");
	else if (event.getSource() == b2)
	    text1.setText("Button2");
	else
	    text1.setText("Button3");
    }
    public void keyTyped(KeyEvent e){}
    public void keyReleased(KeyEvent e){}

    //
    // Look and Feel Actions.
    // 
    
    private class LAFAction extends AbstractAction {
        private String laf;
        
        public LAFAction(String name, String laf)  {
            super(name);
            this.laf = laf;
        }
        
        public void actionPerformed(ActionEvent evt)  {
            try {
                UIManager.setLookAndFeel(laf);
                SwingUtilities.updateComponentTreeUI(SwingButton.this);
            } catch (Exception ex) {
                System.out.println("Unsuported Look and Feel");
            }
        }
    }
    
    private class WindowsLAF extends LAFAction  {
        public WindowsLAF()  {
            super("Windows", "com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
        }
    }

    private class MotifLAF extends LAFAction  {
        public MotifLAF()  {
            super("Motif", "com.sun.java.swing.plaf.motif.MotifLookAndFeel");
        }
    }

    private class MetalLAF extends LAFAction  {
        public MetalLAF()  {
            super("Metal", "javax.swing.plaf.metal.MetalLookAndFeel");
        }
    }
}
<<<<<< SwingButton.java


mark.davidson@Eng 2000-10-30

Comments
PUBLIC COMMENTS .
10-06-2004

EVALUATION Point #1 describes a separate bug and should probably be filed as one. This represents a regression. Point #2 describes a problem in which the default button will become the last button that had the focus. The policy has been implemented in BasicButtonListener.focusGained(). In Windows, the default button follows the focus traversal if the control which has focus is a button. When the focus is on another control, the default button becomes the programatically selected default button. The curent implementation will set the default button as the last button which had the focus. This is not good since it ignores the intension of the developer when they set the JRootPane.setDefaultButton(JButton). The default JRootPane button will have to be saved when the rootpane UI is created or on a property change event when the previous value is null (upon initialization). It will also have to distinguish between programmer initiated setDefaultButton and method calls from the UI. The focusManager would have to track which component has the current focus such that the transition from a JButton (focusLost) to a different component like a JCheckBox (focusGained) will set the default button back to the programer's intended default button. Se also bug 4388686 for insight into the correct behaviour on Windows. mark.davidson@Eng 2001-01-22 This is really a duplicate of 4146858, which has been fixed for merlin-beta. amy.fowler@Eng 2001-02-09
22-01-2001