JDK-6611253 : Java Swing UI field size corrupted when using Windows XP style
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 5.0
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2007-09-29
  • Updated: 2011-07-01
Related Reports
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
JDK 1.5.0_12, also broken with JDK 6 (update 1, 2, 3 and 4)

ADDITIONAL OS VERSION INFORMATION :
Windows XP Service Pack 2


A DESCRIPTION OF THE PROBLEM :
The problem is that when the Windows Theme is set to "Windows XP"
several fields, Chunk Size, Ping Interval and Drives To Crawl field boxes
are corrupted or truncated.

When the Windows Theme is changed to "Windows Classic" the  fields,
1, 2 and 3 are displayed correctly.



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compiling the pasted-in class below and noticed that when you run it with Display Properties /Appearance / Windows_And_Buttons style set to Windows Classic, the UI looks good, when you run it with Windows XP, the UI looks all squished.



EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
You will have to run it and see the difference between Classic and XP style.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.util.StringTokenizer;

import javax.swing.JComponent;
import javax.swing.JOptionPane;

import javax.swing.JDialog;

public class MyDialog extends JDialog implements ActionListener, WindowListener {

    private javax.swing.JPanel contentPane = null;

    private javax.swing.JPanel tabsPanel = null;
    private javax.swing.JTabbedPane optionsTabsPane = null;
    private PSSetupEMOptionsPanel emOptionsPanel = null;
    private javax.swing.JPanel buttonsPanel = null;
	  private javax.swing.JButton okButton = null;
	  private javax.swing.JButton cancelButton = null;
    private String errorField;

    public static void main(String[] args) {
        MyDialog dia = new MyDialog();
        dia.setVisible(true);
    }

    public MyDialog() {
        this((java.awt.Frame) null, false);
    }

    public MyDialog(java.awt.Frame parent, boolean modal) {
        super(parent, "Change Assistant Options", modal);
        initialize();
        defaultFields();
        addWindowListener(this);
    }

    private void defaultFields() {
        defaultEMPanel();
    }

    private void defaultEMPanel() {
        String hubPort;
        hubPort = new String("80");
        if (hubPort != null
            && !(hubPort = hubPort.trim()).equals("")) {
            emOptionsPanel.setEMHubURL(hubPort);
        }
        emOptionsPanel.setChunkSize("1048576");
        emOptionsPanel.setPingInterval("10000");
        emOptionsPanel.setDrivesToCrawl("C:/oracle/product/10.2.0/db_1");
    }

    private void initialize() {
        emOptionsPanel = new PSSetupEMOptionsPanel();
        
        this.setSize(600, 600);
        this.setContentPane(getContentPanel());
        this.setResizable(false);
        getRootPane().setDefaultButton(okButton);
    }
	
    private javax.swing.JPanel getContentPanel() {
        if (contentPane == null) {
            contentPane = new javax.swing.JPanel();
            java.awt.GridBagConstraints consGridBagConstraints65 =
                new java.awt.GridBagConstraints();
            consGridBagConstraints65.gridx = 0;
            consGridBagConstraints65.gridy = 1;
            consGridBagConstraints65.insets = new java.awt.Insets(5,0,5,0);
            consGridBagConstraints65.anchor = java.awt.GridBagConstraints.EAST;
            contentPane.setLayout(new java.awt.GridBagLayout());
            contentPane.add(getTabsPanel(), new java.awt.GridBagConstraints());
            contentPane.add(getButtonsPanel(), consGridBagConstraints65);
            contentPane.setPreferredSize(new java.awt.Dimension(580, 590));
        }
        return contentPane;
    }

    private javax.swing.JPanel getTabsPanel() {
        if (tabsPanel == null) {
            tabsPanel = new javax.swing.JPanel();
            java.awt.GridBagConstraints consGridBagConstraints66 =
                new java.awt.GridBagConstraints();
            consGridBagConstraints66.gridx = 0;
            consGridBagConstraints66.gridy = 0;
            consGridBagConstraints66.weightx = 1.0;
            consGridBagConstraints66.weighty = 1.0;
            consGridBagConstraints66.fill = java.awt.GridBagConstraints.BOTH;
            consGridBagConstraints66.insets = new java.awt.Insets(5, 0, 0, 0);
            tabsPanel.setLayout(new java.awt.GridBagLayout());
            tabsPanel.add(getOptionsTabsPane(), consGridBagConstraints66);
            // # Change the 520
			tabsPanel.setPreferredSize(new java.awt.Dimension(580, 530));
            tabsPanel.setName("tabsPanel");
        }
        return tabsPanel;
    }

    public javax.swing.JTabbedPane getOptionsTabsPane() {
        if (optionsTabsPane == null) {
            refreshTabsPane();
        }
        return optionsTabsPane;
    }

    private void refreshTabsPane() {
        optionsTabsPane = new javax.swing.JTabbedPane();
        optionsTabsPane.addTab(
            "Environment Management",
            null,
            emOptionsPanel,
            "Click here to modify Environment Management options.");
        optionsTabsPane.setMnemonicAt(0, KeyEvent.VK_A);
        optionsTabsPane.setPreferredSize(
            new java.awt.Dimension(580, 430));
    }

    private javax.swing.JPanel getButtonsPanel() {
        if (buttonsPanel == null) {
            buttonsPanel = new javax.swing.JPanel();
            java.awt.FlowLayout layFlowLayout14 = new java.awt.FlowLayout();
            layFlowLayout14.setVgap(2);
            layFlowLayout14.setHgap(10);
            buttonsPanel.setLayout(layFlowLayout14);
            buttonsPanel.add(getOkButton(), null);
            buttonsPanel.add(getCancelButton(), null);
        }
        return buttonsPanel;
    }

	private javax.swing.JButton getOkButton() {
		if(okButton == null) {
			okButton = new javax.swing.JButton();
			okButton.setText("OK");
			okButton.setPreferredSize(new java.awt.Dimension(75,26));
            okButton.addActionListener(this);
            okButton.setMnemonic(KeyEvent.VK_O);
		}
		return okButton;
	}

	private javax.swing.JButton getCancelButton() {
		if(cancelButton == null) {
			cancelButton = new javax.swing.JButton();
			cancelButton.setText("Cancel");
			cancelButton.setPreferredSize(new java.awt.Dimension(75,26));
			cancelButton.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
            cancelButton.addActionListener(this);
            cancelButton.setMnemonic(KeyEvent.VK_C);
		}
		return cancelButton;
	}
 
    public void actionPerformed(ActionEvent e) {
    }

 
  
    public void moveFocusTo(String field) {
        
        if (emOptionsPanel.setFocusTo(field)) {
            optionsTabsPane.setSelectedIndex(optionsTabsPane.indexOfTab("Environment Management"));
        }
    }

    public void setErrorField(String field) {
        errorField = field;
    }

    public void windowActivated(WindowEvent e) { }

    public void windowClosed(WindowEvent e) { }

    public void windowClosing(WindowEvent e) {  }

    public void windowDeactivated(WindowEvent e) { }

    public void windowDeiconified(WindowEvent e) { }

    public void windowIconified(WindowEvent e) { }

    public void windowOpened(WindowEvent e) {
        if (errorField != null) {
            moveFocusTo(errorField);
        }
    }

}

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

Comments
WORK AROUND Use desktop property notifications. In this particular case only two of them are required to be tracked: win.frame.captionHeight and win.frame.sizingBorderWidth. Below is the sample test demonstrating their usage. To list all available properties try following code: String propnames[] = String[])Toolkit.getDefaultToolkit().getDesktopProperty("win.propNames"); System.out.println("Supported windows property names:"); for(int i = 0; i < propnames.length; i++) { System.out.println(propnames[i]); } This API does exist from JDK1.4. ------------------------------------------------------ import java.awt.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; public class Main { public static void main(String[] args) { System.out.println(Toolkit.getDefaultToolkit().getDesktopProperty("win.frame.captionHeight")); Toolkit.getDefaultToolkit().addPropertyChangeListener("win.frame.captionHeight", new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent arg0) { System.out.println("property changed: " +arg0.getOldValue() +" : " +arg0.getNewValue()); } }); Frame f = new Frame("TEST"); f.setVisible(true); } }
30-04-2008

EVALUATION GridBagLayout behavior with its respect to components' minimum size is a well-known problem. However, this problem is caused by another issue: when a window has its size fixed, its client area size depends on the window insets. I think the current AWT behavior is correct: regardless of the current window decorations (insets) the total size of the window is always the same as was specified by setSize/setBounds. To fix the problem we either need to fix GridBagLayout (4238932) or provide a new API about changing the current desktop theme, so application may recalculate the size of all windows with corrected insets.
23-10-2007

EVALUATION A duplicate of 4238932.
23-10-2007

EVALUATION I reproduced this bug on JDK 7 as well the problem looks very familiar - GridBaglayout messes components up when it doesn't have enough space for them the problem is known, when you setSize for a frame it includes frame's decoration also so when you do frame.setSize(600, 600) its contentPane will be 592 x 568 with WindowsXP theme decorations are a bit wider and contentPane is a bit smaller and that is the reason why GridBagLayout doesn't have enough space for components possible workaround is to take frame's insets into account frame.pack(); // this is important Insets insets = frame.getInsets(); frame.setSize(600 + insets.left + insets.right, 600 + insets.top + insets.bottom); it won't work when you change Windows theme on the fly, but will work well at application's start reassigned to AWT to let them add any relevant information
10-10-2007

WORK AROUND frame.pack(); // this is important Insets insets = frame.getInsets(); frame.setSize(600 + insets.left + insets.right, 600 + insets.top + insets.bottom); it won't work when you change Windows theme on the fly, but will work well at application's start
10-10-2007