SYNOPSIS
--------
Regression: JComponent.revalidate() has no effect on invisible components
JDK VERSION
-----------
JDK 7 b77 and later (does not occur with b76 or earlier)
Does not occur with 5.0 or 6.
DESCRIPTION
-----------
Calls to JComponent.revalidate() have no effect on components
that are not showing at the moment of this call but will become visible
before the end of the current AWT event handling.
In all releases of 5.0 and 6, a revalidate() call has an effect if the Swing component has become visible by the time the delayed revalidation is executed, so this seems to be a regression (although the specification for revalidate() is not completely clear on the correct behaviour).
REPRODUCTION INSTRUCTIONS
-------------------------
1. Compile and run the attached test case.
2. Press the "Show/hide dialog" button. A dialog appears.
3. Close the dialog, either by pressing the button again or through the close icon.
4. Press the "Show/hide dialog" button again. The dialog reappears.
With 5.0 and 6 the dialog is painted correctly, but in JDK 7 it is incomplete. Only after resizing or typing some characters in the text field does it repaint itself correctly.
WORKAROUND
----------
Make any invisible components visible by calling setVisible(true) immediately before calling revalidate().
TESTCASE
--------
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class TestJDK7RevalidateBug {
static final boolean WORKAROUND = false;
static class MyDialog extends JDialog {
JPanel mainPanel;
JLabel title;
int counter;
Box inputPanel;
MyDialog() {
mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
title = new JLabel();
mainPanel.add(title, BorderLayout.NORTH);
getContentPane().add(mainPanel);
setSize(150, 150);
}
void showMe() {
inputPanel = new Box(BoxLayout.PAGE_AXIS);
inputPanel.add(new JLabel("Please type something here:"));
inputPanel.add(new JTextArea());
mainPanel.add(inputPanel);
counter++;
title.setText("Dialog #"+counter);
if (WORKAROUND)
setVisible(true);
mainPanel.revalidate();
mainPanel.repaint();
if (!WORKAROUND)
setVisible(true);
}
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
if (!visible) {
if (inputPanel != null) {
mainPanel.remove(inputPanel);
inputPanel = null;
}
}
}
}
static class MainFrame extends JFrame {
MyDialog dialog;
MainFrame() {
dialog = new MyDialog();
final JButton button = new JButton();
button.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent event) {
if (dialog.isShowing()) {
dialog.setVisible(false);
} else {
dialog.showMe();
}
}
});
button.setText("Show/hide dialog");
getContentPane().add(button);
setSize(200, 150);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
MainFrame frame = new MainFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}