2012-12-23 37 views
5

Tôi đang cố gắng tạo GUI nhỏ, nó có 2 JButtons và 2 JPanels với một số hoạt ảnh vẽ trên mỗi hình ảnh. Theo mặc định, nó phải hiển thị JPanel đầu tiên và bằng cách nhấp vào JButton thứ hai, tôi muốn xem JPanel thứ hai của mình. Vì vậy: tôi tạo JFrame, Panel1 và Panel2, nơi tôi đã vẽ hoạt ảnh của mình, tạo Button1 và Button2 và thêm vào chúng ActionListeners. Tôi cũng có MainPanel có trong một biến trường i. Bằng cách thay đổi "i" constructor của tôi thêm vào MainPanel hoặc Panel1 (mặc định) hoặc Panel2 (bằng cách nhấp vào JButton2 tôi thay đổi i). Hơn tôi thêm MainPanel này vào khung của tôi. Vì vậy, câu hỏi của tôi: trong lớp MainPanel tôi có phương pháp refreshMe, những gì tôi nên viết ở đó để làm cho GUI của tôi hoạt động tốt? Cảm ơn. Đây là mã của tôi:Cách thêm JPanel bằng cách nhấp vào JButton?

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(); 
      } 
     }); 

    } 

} 

Trả lời

8

Để phản ánh những thay đổi sau khi thêm/loại bỏ hay thay đổi kích thước một thành phần đó là trên một cuộc gọi có thể nhìn thấy chứa revalidate()repaint() trên dụ container sau khi thêm/loại bỏ hay thay đổi kích thước thành phần.

Mặc dù điều này sẽ không làm việc trong mã của bạn lý do chính là bên trong lớp JButton bạn tạo một thể hiện mới của MainPanel trong khi thực tế 2 JButtons nên chia sẻ các trường hợp duy nhất mà đang được sử dụng (bạn có thể vượt qua MainPanel dụ cho JButton s nhà thầu, nhưng bạn nên không thực sự được mở rộng một JButton trừ việc thêm chức năng tùy chỉnh):

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() { 
    } 
} 

một vài gợi ý khác trên mã của bạn:

  • Không mở rộng JButton lớp không cần thiết, chỉ cần tạo một thể hiện của JButton giống như bạn đã thực hiện với JFrame và các phương thức gọi trên JButton ví dụ.

  • Đừng quên tạo/thao tác các thành phần Swing trên Event Dispatch Thread, qua khối SwingUtilities.invokeLater(..), đọc here để biết thêm.

Đây là mã của bạn cố định (trên gợi ý vv thực hiện):

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); 
    } 
} 

Tuy nhiên Id đề nghị một cái gì đó đơn giản hơn, may mắn thay bạn có 2 lựa chọn:

1) Sử dụng CardLayout mà sẽ cho phép bạn để lật giữa nhiều thành phần trên một đơn JFrame/container.

Dưới đây là một ví dụ tôi đưa ra:

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) Sử dụng removeAll() kỹ thuật tức là gọi frame.getContentPane().removeAll() mà sẽ loại bỏ tất cả các thành phần hiện có trên JFrame và hơn thêm nội dung mới và gọi revalidate()repaint() (cũng có thể muốn thêm pack() vào đó) trên JFrame thể hiện để phản ánh thay đổi. Mặc dù Id khuyên bạn nên CardLayout.

+0

Cảm ơn bạn đã sửa mã và ví dụ của mình, điều này sẽ giúp ích rất nhiều! Có, CardLayout giải quyết vấn đề của tôi. – user1924939

3

Tôi nghĩ bạn chỉ có thể sử dụng CardLayout để thực hiện chức năng của mình. Vui lòng tham khảo here