我有一个对话框,其中附加控件会导致对话框在出现时调整大小。有一天我可能会找到一种方法来制作动画,但现在我只满足于调整大小。问题是,它闪烁。
我将问题简化为测试:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
/**
* Shows flickering when resizing a dialog.
*/
public class FlickerTest extends FakeJDialog
{
public FlickerTest()
{
super((Window) null, "Flicker Test");
JButton button = new JButton("Bigger!");
button.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent event)
{
Window window = SwingUtilities.getWindowAncestor((Component) event.getSource());
window.setSize(window.getWidth(), window.getHeight() + 20);
}
});
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.setOpaque(true);
contentPane.add(button, BorderLayout.PAGE_START);
JRootPane rootPane = new JRootPane();
rootPane.setContentPane(contentPane);
add(rootPane);
setResizable(false);
pack();
setLocationRelativeTo(null);
}
public static void main(String[] args) throws Exception
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
new FlickerTest().setVisible(true);
}
});
}
}
每次单击按钮时,窗口都会改变大小。在相当长的一段时间内,对话框底部变黑。通过录制我的屏幕,我能够得到一个截图来展示它:
我怎样才能避免这种情况?
进一步的调查:
Dialog 的以下子类表现出与 JDialog 相同的闪烁:
import java.awt.Component;
import java.awt.Container;
import java.awt.Dialog;
import java.awt.Window;
import javax.swing.JLayeredPane;
import javax.swing.JRootPane;
import javax.swing.RootPaneContainer;
/**
* Minimal subclass of Dialog required to cause the flickering.
* If you comment out "implements RootPaneContainer", the flickering goes away.
*/
public class FakeJDialog extends Dialog implements RootPaneContainer
{
public FakeJDialog(Window owner, String title)
{
super(owner, title, Dialog.ModalityType.MODELESS);
}
public JRootPane getRootPane()
{
throw new UnsupportedOperationException();
}
public Container getContentPane()
{
throw new UnsupportedOperationException();
}
public void setContentPane(Container contentPane)
{
throw new UnsupportedOperationException();
}
public JLayeredPane getLayeredPane()
{
throw new UnsupportedOperationException();
}
public void setLayeredPane(JLayeredPane layeredPane)
{
throw new UnsupportedOperationException();
}
public Component getGlassPane()
{
throw new UnsupportedOperationException();
}
public void setGlassPane(Component glassPane)
{
throw new UnsupportedOperationException();
}
}
我觉得这很有趣,因为仅仅注释掉就implements RootPaneContainer
足以完全改变行为。Swing 或 AWT 中的某些东西显然是在寻找这个接口并专门处理这些组件。所以这表明没有 JDialog 的子类可以避免这个问题。