2012-12-23 3 views
5

Ich versuche, eine kleine GUI zu erstellen, es hat 2 JButtons und 2 JPanels mit einigen Zeichnungsanimation auf jedem von ihnen. Standardmäßig muss das erste JPanel angezeigt werden, und durch Klicken auf das zweite JButton möchte ich mein zweites JPanel sehen. Also: Ich erstelle JFrame, Panel1 und Panel2, wo ich meine Animationen gezeichnet habe, Button1 und Button2 erstellt und ihnen ActionListeners hinzugefügt habe. Ich habe auch MainPanel, das in einer Feldvariablen i hat. Durch Ändern dieses "i" fügt mein Konstruktor zu MainPanel entweder Panel1 (Standard) oder Panel2 hinzu (indem ich auf JButton2 wechsle, ändere ich). Dann füge ich dieses MainPanel meinem Frame hinzu. Also meine Frage: In der Klasse MainPanel habe ich die refreshMe-Methode, was soll ich da schreiben, damit meine GUI richtig funktioniert? Vielen Dank. Hier ist mein Code:Wie Sie JPanel hinzufügen, indem Sie auf JButton klicken?

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

    } 

} 

Antwort

8

Um Änderungen widerzuspiegeln nach dem Hinzufügen/Entfernen oder Ändern der Größe einer Komponente, die auf einem sichtbaren Behälter Anruf revalidate() und repaint() auf die Behälter-Instanz nach dem Hinzufügen/Entfernen oder Ändern der Größe der Komponente.

Obwohl dies wird Ihnen eine neue Instanz von MainPanel, wenn die 2 JButtons in der Tat neu innerhalb JButton Klassen ist der Hauptgrund, in Ihrem Code nicht funktionieren sollte die einzige Instanz teilen, die verwendet wird (Sie Mainpanel-Instanz die JButton passieren könnte s Bauer, aber Sie sollten nicht wirklich sein erstreckt ein JButton es sei denn, das Hinzufügen von benutzerdefinierten Funktionen):

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

einige andere Vorschläge auf Ihren Code:

  • Erweitern Sie nicht unnötig JButton Klasse, erstellen Sie einfach eine Instanz von JButton wie Sie mit JFrame und rufen Sie Methoden auf JButton Instanz.

  • Vergessen Sie nicht, Swing-Komponenten auf Event Dispatch Thread über SwingUtilities.invokeLater(..) Block zu erstellen/manipulieren, lesen here für mehr.

Hier ist der Code festgelegt (siehe oben Vorschläge umgesetzt 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); 
    } 
} 

jedoch etwas einfacher, Id vorschlagen zum Glück haben Sie die Wahl zwischen 2:

1) Verwenden Sie CardLayout, die Sie ermöglichen zwischen mehreren Komponenten auf einem einzigen JFrame/Container zu wechseln. Hier

ist ein Beispiel, das ich gemacht:

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) Verwenden Sie removeAll() Technik dh Aufruf frame.getContentPane().removeAll() die alle Komponenten aktuell JFrame entfernen wird und als die neuen Inhalte hinzufügen und rufen revalidate() und repaint() (auch könnte pack() dort hinzufügen) auf JFrame Instanz, um Änderungen zu reflektieren. Obwohl Id CardLayout empfehlen.

+0

Vielen Dank für die Korrektur meines Codes und Beispiel, das hilft sehr! Ja, CardLayout löst mein Problem. – user1924939

3

Ich glaube, Sie nur CardLayout Ihre Funktion implementieren können. Siehe here