2011-09-21 67 views
2

這是我的代碼。在展示之前設計的框架(添加了面板)時,我沒有任何問題。將面板動態添加到空JFrame時遇到此問題。動態添加JPanels不會顯示在Swing中

package com.mytunes.controllers; 

import com.mytunes.views.*; 
import com.mytunes.views.panels.*; 
import java.awt.BorderLayout; 
import java.lang.reflect.Constructor; 
import java.lang.reflect.InvocationTargetException; 
import java.util.ArrayList; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.JFrame; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 
import javax.swing.WindowConstants; 


public class GUIController { 
    ArrayList<JFrame> displayFrames = new ArrayList<JFrame>(); 

    JPanel displayPanel; 
    HeaderPanel headerPanel = new HeaderPanel(); 
    FooterPanel footerPanel = new FooterPanel(); 


    public int showFrame(String frameName, Object controller){ 
     Class c; 
     Constructor ctr; 
     int lastFrame = -1; 

     try { 

      // call a class dynamically 
      c = Class.forName("com.mytunes.views.frames." + frameName + "Frame"); 
      // calll a constructor of a class 
      ctr = c.getConstructor(SessionController.class); 
      // instantiate dynamically created class 
      displayFrames.add((JFrame) ctr.newInstance(controller)); 

      // get the index of frame just added 
      lastFrame = displayFrames.size()-1; 

      displayFrames.get(lastFrame).setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
      displayFrames.get(lastFrame).pack(); 
      displayFrames.get(lastFrame).setLocationRelativeTo(null); 

      // hide it by default. 
      displayFrames.get(displayFrames.size()-1).setVisible(false); 

     } catch (InstantiationException ex) { 
      Logger.getLogger(GUIController.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (IllegalAccessException ex) { 
      Logger.getLogger(GUIController.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (IllegalArgumentException ex) { 
      Logger.getLogger(GUIController.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (InvocationTargetException ex) { 
      Logger.getLogger(GUIController.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (NoSuchMethodException ex) { 
      Logger.getLogger(GUIController.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (SecurityException ex) { 
      Logger.getLogger(GUIController.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (ClassNotFoundException ex) { 
      JOptionPane.showMessageDialog(null, "Error while loading class 'com.mytunes.view.frames." + frameName + "'"); 
     } 

     System.out.println(lastFrame); 
     return lastFrame; 

    } 

    //-------------show panels --------------// 
    public void showOperator(String frame, Object controller){ 

     // this works fine! this frame is already having Panels 
     int f = showFrame(frame, controller); 
     displayFrames.get(f).setVisible(true); 
    } 
    public void showEnterPIN(String frame, Object controller){ 


     int f = showFrame(frame, controller); 
     displayFrames.get(f).getContentPane().add(new EnterPINPanel(), BorderLayout.CENTER); 
     displayFrames.get(f).setVisible(true); 

     //  Try every following ways to show the "Dynamically added" panels 
     //  displayFrames.get(f).getContentPane().removeAll(); 
     //  displayFrames.get(f).getContentPane().invalidate(); 
     //  displayFrames.get(f).getContentPane().add(new EnterPINPanel(), BorderLayout.PAGE_START); 
     //  displayFrames.get(f).getContentPane().validate(); 
     //  displayFrames.get(f).pack(); 
     //  displayFrames.get(f).setVisible(true); 

    } 

} 

欣賞是否有人能夠發現我這個問題。謝謝。

+0

查看**編輯2 **在我的回答下面 –

回答

5

如果將組件添加到容器,則需要通過調用revalidate()然後有時在容器上調用repaint();來通知容器的佈局管理器來佈置它們包含的所有組件。所以,像...

JPanel contentPane = (JPanel)displayFrames.get(f).getContentPane(); 
contentPane.add(new EnterPINPanel(), BorderLayout.CENTER); 
contentPane.revalidate(); 
contentPane.repaint(); 

說了這麼多,你的應用程序設計看起來有點不同。你真的使用JFrames的ArrayList?大多數真實世界的應用程序不使用一堆單獨的窗口,而是在一個主窗口中交換顯示,並且通過使用一個JFrame並通過CardLayout交換視圖,您可以使用Swing做類似的事情。

編輯2
如果你嘗試:

int f = showFrame(frame, controller); 
    JPanel contentPane = (JPanel)displayFrames.get(f).getContentPane(); 
    contentPane.removeAll(); 
    contentPane.setLayout(new BorderLayout()); // just to be sure 
    contentPane.add(headerPanel, BorderLayout.PAGE_START); 
    contentPane.add(new EnterPINPanel(), BorderLayout.CENTER); 
    contentPane.add(footerPanel, BorderLayout.PAGE_END); 
    contentPane.revalidate(); // *** note that it's **re**validate 
    contentPane.repaint(); 
    displayFrames.get(f).setVisible(true); 

同樣地,如果這沒有幫助,那麼你應該創建和發佈"Short, Self Contained, Correct (Compilable), Example" or SSCCE

+0

+1快速回復和最佳實踐小費!發現它對像我這樣的新手有幫助:)我想要實現一個「返回」按鈕,用戶可以在數據輸入窗體中查看和編輯以前輸入的exField數據。 – coder9

+1

這很好,但有更好的方法來實現「回去」。想到一個簡單的堆棧。 –

+0

我仍然無法將面板添加到該ArrayList中的一個框架。適用於非數組列表框架。 – coder9

0

這工作

JFrame contentPane = new JFrame();  
    contentPane.getContentPane().add(new EnterPINPanel(), BorderLayout.CENTER); 
    contentPane.setVisible(true); 

但不是這個

int f = <ArrayList index of last inserted Frame> 
displayFrames.get(f).getContentPane().add(headerPanel, BorderLayout.PAGE_START); 
displayFrames.get(f).getContentPane().add(new EnterPINPanel(), BorderLayout.CENTER); 
displayFrames.get(f).getContentPane().add(footerPanel, BorderLayout.PAGE_END); 
displayFrames.get(f).getContentPane().validate(); 
displayFrames.get(f).getContentPane().repaint(); 
displayFrames.get(f).setVisible(true); 
+1

再一次,如果你仍然堅持下去,我感覺只有你創建和發佈[SSCCE](http://SSCCE.org)才能真正幫助你。 –

+0

嗨氣墊船:非常感謝!我使用堆棧,現在它工作正常!我認爲情況並非如此,但我認爲這是一個鑄造問題。我通過創建本地JFrame引用並將它們分配給由newInstance(...)返回的對象來實現它。即「JFrame ff =(JFrame)ctr.newInstance(controller);」 – coder9

+0

請閱讀http://stackoverflow.com/questions/6988317/dynamically-add-components-to-a-jdialog/6989230#6989230,對於LayoutManager作爲BorderLayout(只有一個JComponent可以佔用混凝土區域)是否符合預期的輸出GUI,但更好的是使用revalidate()@ HFOE + 1 – mKorbel