2014-03-12 38 views
0

我想逐步修改一個java JFrame設計結構,就像這個簡單的例子。在循環中,我正在增加JPanel的de preferredWidth並使用方法pack()。但顯然該包裝方法被忽略。如果我把這個包放在循環中,只用一次,它就可以工作。任何人都知道原因和可能的解決方案?在循環中使用JFrame.pack()

public class Calculadora extends JFrame { 

private JPanel pnl = new JPanel(); 
private boolean flag; 

public Calculadora() { 
    JPanel pnlPrincipal = new JPanel(); 
    pnlPrincipal.setPreferredSize(new Dimension(300, 300)); 
    pnlPrincipal.setBackground(Color.BLACK); 
    JButton btnAnexo = new JButton("Anexo"); 
    btnAnexo.addActionListener(new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      if (flag) { 
       closeAnexo(); 
       flag = false; 
      } else { 
       openAnexo(); 
       flag = true; 
      } 
     } 
    }); 
    pnlPrincipal.add(btnAnexo); 
    this.pnl.setBackground(Color.WHITE); 
    this.pnl.setPreferredSize(new Dimension(0, 300)); 
    this.add(pnl, BorderLayout.EAST); 
    this.add(pnlPrincipal, BorderLayout.CENTER); 
    this.pack(); 
    this.setVisible(true); 
} 

private void openAnexo() { 
    new Thread() { 
     @Override 
     public void run() { 
      for (int i = pnl.getWidth(); i <= 200; i++) { 
       pnl.setPreferredSize(new Dimension(i, 300)); 
       pack(); 
      } 
     } 
    }.start(); 
} 

private void closeAnexo() { 
    new Thread() { 
     @Override 
     public void run() { 
      for (int i = pnl.getWidth(); i >= 0; i--) { 
       pnl.setPreferredSize(new Dimension(i, 300)); 
       pack(); 
      } 
     } 
    }.start(); 
} 

public static void main(String[] args) { 
    new Calculadora(); 
} 
} 

回答

3

這裏:

private void openAnexo() { 
    new Thread() { 
     @Override 
     public void run() { 
      for (int i = pnl.getWidth(); i <= 200; i++) { 
       pnl.setPreferredSize(new Dimension(i, 300)); 
       pack(); 
      } 
     } 
    }.start(); 
} 

Swing組件必須創建/更新的Event Dispatch Thread。話雖如此,你的線程阻塞了EDT,導致GUI變得無法響應。您應該使用SwingUtilities.invokeLater()與EDT同步此新線程。或者甚至更好,你可以使用Swing Timer這個便利的類來處理所有這些併發的東西,從而完成重複的任務。

例如:

private void openAnexo() { 
    javax.swing.Timer timer = new javax.swing.Timer(200, new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      int width = pnl.getWidth(); 
      if(width > 200) { 
       ((javax.swing.Timer)e.getSource()).stop(); 
      } else { 
       pnl.setPreferredSize(new Dimension(width + 1, 300)); 
       Calculadora.this.pack(); 
      } 

     } 
    }); 
    timer.setRepeats(true); 
    timer.setDelay(200); 
    timer.start(); 
} 

看看到How to Use Swing Timers教程一個更好的解釋。

我不知道你想用這個做什麼,但要注意這個:Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?(是的,我們應該)。

+0

非常感謝!其作品! –

+0

@ user2308270不客氣:) – dic19

0

你應該用適當的layout managerBorderLayout在這種情況下:

JPanel pnlPrincipal = new JPanel(); 
pnlPrincipal.setLayout(new BorderLayout()); 

// or 

JPanel pnlPrincipal = new JPanel(new BorderLayout()); 
+0

問題依然存在。因爲我在JFrame中添加了第二個JPanel,而不是在這個JPanel中。所以佈局沒有什麼區別。 –