我有一個對話框,其中附加控件導致對話框出現時調整大小。有一天,我可能會找到一種方法來創建動畫,但現在我滿足於調整大小。問題是,它閃爍。如何在調整Swing窗口大小時避免閃爍?
我的問題減少到一個測試:
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);
}
});
}
}
我每次點擊按鈕,窗口尺寸改變。對於明顯的時間量,對話框的底部會變黑。通過記錄我的屏幕上,我能得到一個屏幕截圖,展示它:
我怎樣才能避免這種情況?
進一步調查:
對話框下面的子類,表現出相同的閃爍爲的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的子類可以避免這個問題。
我不認爲你可以 – MadProgrammer
嗯...有趣的是,雖然我不能重現它(Vista,jdk7) – kleopatra
+1 kleopatra,我使用Windows 7 64位JDK 7u9並沒有閃爍。 @Trejkaz無論如何你爲什麼使用'Dialog'?應該使用'JDialog'。也不要調用'setSize'而是重載'getPreferredSize()'並且使它返回'height'和'width'的尺寸(不要忘記爲高度和寬度設置setters),然後簡單地調用'revalidate()'和'pack )在調用具有適當值的setter後調用'JDialog'。請參閱[here](http://stackoverflow.com/questions/13549976/how-to-change-the-dimension-of-a-component-in-a-jframe/13551229#13551229)例如 –