2012-12-23 51 views
5

我試圖創建一個小的GUI,它有2個JButtons和2個JPanels,每個都有一些繪圖動畫。默認情況下,它必須顯示第一個JPanel,並通過點擊第二個JButton我想看到我的第二個JPanel。所以:我創建了JFrame,Panel1和Panel2,在其中繪製了我的動畫,創建了Button1和Button2並向它們添加了ActionListeners。我也有一個字段變量i的MainPanel。通過改變這個「我」我的構造函數添加到MainPanel要麼Panel1(默認)或Panel2(通過點擊JButton2我改變我)。比我添加這個MainPanel到我的框架。所以我的問題:在類MainPanel中我有refreshMe方法,我應該寫什麼來使我的GUI正常工作?謝謝。這裏是我的代碼:如何通過點擊JButton添加JPanel?

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class GuiTest { 

    public static void main(String[] args) { 
     JFrame f = new JFrame(); 
     MainPanel myPanel = new MainPanel(); 
     f.add(myPanel); 
     Button1 button1 = new Button1(); 
     Button2 button2 = new Button2(); 
     myPanel.add(button1); 
     myPanel.add(button2); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.pack(); 
     f.setVisible(true); 
    } 
} 

class MainPanel extends JPanel { 
    Panel1 p1 = new Panel1(); 
    Panel2 p2 = new Panel2(); 
    public int i = 1; //this is being changed later by clicking JButton 
    // I use this setter later in actionPerformed in order to change i 
    public void setI(int i) { 
     this.i = i; 
    } 

    MainPanel() { 
     if (i == 1) { 
      this.add(p1); 
     } 
     if (i == 2) { 
      this.add(p2); 
     } 
    } 

    public void refreshMe() { 
     // Need some help here: 
     // I don't know what should I write, how to make a repaint of myPanel? 
     System.out.println("just test, if the method refreshMe working by clicking some button"); 
    } 
} 

class Panel1 extends JPanel { 

    public Panel1() { 
     this.setBackground(Color.BLUE); 
     // a lot of drawing stuff going on here 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(200, 200); 
    } 
} 

class Panel2 extends JPanel { 

    public Panel2() { 
     this.setBackground(Color.GREEN); 
     // a lot of drawing stuff going on here 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(200, 200); 
    } 

} 

class Button1 extends JButton { 
    MainPanel someObj1 = new MainPanel(); 

    Button1() { 
     setText("Show Annimation A"); 
     addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       someObj1.setI(1); 
       System.out.println("The variable i is now: " + someObj1.i); 
       someObj1.refreshMe(); 

      } 
     }); 
    } 

} 

class Button2 extends JButton { 
    MainPanel someObj2 = new MainPanel(); 

    Button2() { 
     setText("Show Annimation B"); 
     addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       someObj2.setI(2); 
       System.out.println("The variable i is now: " + someObj2.i); 
       someObj2.refreshMe(); 
      } 
     }); 

    } 

} 

回答

8

爲了反映添加/移除或調整一個組件,它是在添加/移除或調整所述部件後可見容器呼叫revalidate()repaint()在容器實例之後的變化。

雖然這不會在你的代碼工作,主要的理由是一個JButton類中重新創建的MainPanel一個新實例,而實際上2 JButtons應該分享其正在使用的單個實例(你可以傳遞的mainPanel實例的JButton小號構造函數,但你真的不應該被延伸的JButton除非添加自定義功能):

class Button2 extends JButton { 
    MainPanel someObj2 = new MainPanel();//you create an instance of MainPanel which isnt even showing and than do changes on that, this way you will never see any of the changes 

    Button2() { 
    } 
} 

幾個在你的代碼的其他建議:

  • 不必擴展JButton類,只需創建JButton的實例,就像您使用JFrame所做的一樣,並調用JButton實例的方法。

  • 不要忘記創建/操作Event Dispatch Thread上的Swing組件,通過SwingUtilities.invokeLater(..)塊,閱讀here瞭解更多信息。

這裏是你的代碼固定(以上建議ECT實現):

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class Test { 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       JFrame f = new JFrame(); 

       final MainPanel myPanel = new MainPanel(); 
       f.add(myPanel); 

       JButton button1 = new JButton("Show Animation A"); 
       JButton button2 = new JButton("Show Animation B"); 

       button1.addActionListener(new ActionListener() { 
        @Override 
        public void actionPerformed(ActionEvent e) { 
         myPanel.setI(1); 
         System.out.println("The variable i is now: " + myPanel.i); 
         myPanel.refreshMe(); 
        } 
       }); 
       button2.addActionListener(new ActionListener() { 
        @Override 
        public void actionPerformed(ActionEvent e) { 
         myPanel.setI(2); 
         System.out.println("The variable i is now: " + myPanel.i); 
         myPanel.refreshMe(); 
        } 
       }); 

       myPanel.add(button1); 
       myPanel.add(button2); 
       myPanel.checkPanel(); 

       f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

       f.pack(); 
       f.setVisible(true); 
      } 
     }); 
    } 
} 

class MainPanel extends JPanel { 

    Panel1 p1 = new Panel1(); 
    Panel2 p2 = new Panel2(); 
    public int i = 1; //this is being changed later by clicking JButton 
    // I use this setter later in actionPerformed in order to change i 

    public void setI(int i) { 
     this.i = i; 
    } 

    public void refreshMe() { 
     checkPanel(); 

     revalidate(); 
     repaint(); 
     // Need some help here: 
     // I don't know what should I write, how to make a repaint of myPanel? 
     System.out.println("just test, if the method refreshMe working by clicking some button"); 
    } 

    public void checkPanel() { 
     if (i == 1) { 
      this.add(p1); 
      this.remove(p2);//or it will remain there as this is default flowlayout 
     } else if (i == 2) { 
      this.add(p2); 
      this.remove(p1); 
     } 
    } 
} 

class Panel1 extends JPanel { 

    public Panel1() { 
     this.setBackground(Color.BLUE); 
     // a lot of drawing stuff going on here 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(200, 200); 
    } 
} 

class Panel2 extends JPanel { 

    public Panel2() { 
     this.setBackground(Color.GREEN); 
     // a lot of drawing stuff going on here 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(200, 200); 
    } 
} 

但是標識表明簡單的東西,幸好你有2種選擇:

1)使用CardLayout這將允許你在單個JFrame /容器上的多個組件之間翻轉。

這裏是我做了一個例子:

enter image description here

import java.awt.BorderLayout; 
import java.awt.CardLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class Test { 

    private final static String PANEL1 = "panel 1"; 
    private final static String PANEL2 = "panel 2"; 

    public Test() { 
     initComponents(); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new Test(); 
      } 
     }); 
    } 

    private void initComponents() { 
     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     JPanel panel1 = new JPanel(); 
     panel1.add(new JLabel("Panel 1")); 

     JPanel panel2 = new JPanel(); 
     panel2.add(new JLabel("Panel 2")); 

     //Create the panel that contains the "cards". 
     final JPanel cards = new JPanel(new CardLayout()); 
     cards.add(panel1, PANEL1); 
     cards.add(panel2, PANEL2); 

     //create button to allow chnage to next card 
     JButton buttonNext = new JButton(">"); 
     buttonNext.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent ae) { 
       CardLayout cl = (CardLayout) (cards.getLayout());//get cards 
       cl.next(cards); 
      } 
     }); 

     //create button to allow chnage to previous card 
     JButton buttonPrev = new JButton("<"); 
     buttonPrev.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent ae) { 
       CardLayout cl = (CardLayout) (cards.getLayout());//get cards 
       cl.previous(cards); 
      } 
     }); 

     //create panel to hold buttons which will allow switching between cards 
     JPanel buttonPanel = new JPanel(); 
     buttonPanel.add(buttonPrev); 
     buttonPanel.add(buttonNext); 


     frame.add(cards); 
     frame.add(buttonPanel, BorderLayout.SOUTH); 

     frame.pack(); 
     frame.setVisible(true); 
    } 
} 

2)使用removeAll()技術即呼叫frame.getContentPane().removeAll()將目前去除JFrame所有組件和不是增加新的內容,並呼籲revalidate()repaint() (也可能需要在pack()中添加)在JFrame實例上以反映更改。雖然Id建議CardLayout

+0

感謝您糾正我的代碼和示例,這有助於很多!是的,CardLayout解決了我的問題。 – user1924939

3

我想你可以用CardLayout來實現你的功能。請參閱here