2012-11-29 116 views
3

我有一個對話框,其中附加控件導致對話框出現時調整大小。有一天,我可能會找到一種方法來創建動畫,但現在我滿足於調整大小。問題是,它閃爍。如何在調整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); 
      } 
     }); 
    } 
} 

我每次點擊按鈕,窗口尺寸改變。對於明顯的時間量,對話框的底部會變黑。通過記錄我的屏幕上,我能得到一個屏幕截圖,展示它:

enter image description here

我怎樣才能避免這種情況?

進一步調查:

對話框下面的子類,表現出相同的閃爍爲的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的子類可以避免這個問題。

+0

我不認爲你可以 – MadProgrammer

+1

嗯...有趣的是,雖然我不能重現它(Vista,jdk7) – kleopatra

+0

+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)例如 –

回答

2

我不相信有一種解決方法與JDialog。但是,java.awt.Dialog沒有此問題。

+0

哇,你說得對,沒有閃爍,我會看看這兩個並試圖找出它是什麼關於JDialog是什麼使這種情況發生的......也許我可以繞過它 – Trejkaz

+0

將所有Swing內容放入基於AWT的頂級容器中應該很少出現問題。請參閱[混合重量級和輕量級組件](http://www.oracle.com/technetwork/articles/java/mixing-components-433992.html)以獲取詳細信息。 –

+0

是的,我最大的擔憂是以重新實現JDialog在做的事情,即Dialog不是的 – Trejkaz

0

試試這個,我做了這消除除了幾乎完全

閃爍爲例U將得到十分顯着調整角落

enter image description here

/* 
* resizing swing trick in Win7+Aero demo 
* @author: s1w_ 
*/ 
import java.awt.event.*; 
import java.awt.*; 
import javax.swing.event.*; 
import javax.swing.*; 

class ResizeHookDemo extends JDialog { 
    private final static int width = 580, height = 350; 
    private final JFileChooser fc; 
    private java.awt.geom.GeneralPath gp; 

    public ResizeHookDemo() { 
    super((JDialog)null, "Choose File", true); 

    fc = new JFileChooser() { 

    @Override 
    public void paint(Graphics g) { 
     super.paint(g); 
     int w = getWidth(); 
     int h = getHeight(); 
     g.setColor(new Color(150, 150, 150, 200)); 
     g.drawLine(w-7, h, w, h-7); 
     g.drawLine(w-11, h, w, h-11); 
     g.drawLine(w-15, h, w, h-15); 

     gp = new java.awt.geom.GeneralPath(); 
     gp.moveTo(w-17, h); 
     gp.lineTo(w, h-17); 
     gp.lineTo(w, h); 
     gp.closePath(); 
    } 

    }; 
    fc.addActionListener(new ActionListener() { 

     public void actionPerformed(ActionEvent e) { 
     if (e.getActionCommand().equals("CancelSelection")) { 
      setVisible(false); 
      // action... 
     } 
     else if (e.getActionCommand().equals("ApproveSelection")) { 
      setVisible(false); 
      // action... 
     } 
     } 
    }); 

    MouseInputListener resizeHook = new MouseInputAdapter() { 
     private Point startPos = null; 

     public void mousePressed(MouseEvent e) { 
     if (gp.contains(e.getPoint())) 
      startPos = new Point(getWidth()-e.getX(), getHeight()-e.getY()); 
     } 

     public void mouseReleased(MouseEvent mouseEvent) { 
     startPos = null; 
     } 

     public void mouseMoved(MouseEvent e) { 
     if (gp.contains(e.getPoint())) 
      setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR)); 
     else 
      setCursor(Cursor.getDefaultCursor()); 
     } 

     public void mouseDragged(MouseEvent e) { 
     if (startPos != null) { 

      int dx = e.getX() + startPos.x; 
      int dy = e.getY() + startPos.y; 

      setSize(dx, dy); 
      repaint(); 
     } 
     } 
    }; 

    fc.addMouseMotionListener(resizeHook); 
    fc.addMouseListener(resizeHook); 
    fc.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 20)); 
    add(fc); 

    setResizable(false); 

    setMinimumSize(new Dimension(width, height)); 
    setDefaultCloseOperation(HIDE_ON_CLOSE); 
    setLocationRelativeTo(null); 
    } 

    public static void main(String args[]) { 
    System.out.println("Starting demo..."); 
    SwingUtilities.invokeLater(new Runnable() { 

     @Override 
     public void run() { 
     new ResizeHookDemo().setVisible(true); 
     } 
    }); 
    } 
} 
相關問題