Swing MVC Ein JFrame, mehrere JPanels

stulleman

Bekanntes Mitglied
Guten Abend!
Mein Programm soll auf MVC aufbauen, und nur in einem JFrame stattfinden.
Ich habe aber mehrere Menüs und will dafür verschiedene JPanels benutzen.

Mein Controller erzeugt ein neuen JFrame und der JFrame wiederum ein neues JPanel.
Wie würde ich jetzt z.B. auf "Knopfdruck" ein neues JPanel laden?

Vielleicht habt ihr ja eine Idee!
Danke schon mal!

Max
 
Zum Beispiel die Panel in einem CardLayout anordnen und dann immer das gewünschte Panel auswählen und anzeigen lassen.
 
Zum Thema MVC:

Ich hab hier nen gutes Beispiel, das das Model-View-Controller-Prinzip verdeutlicht. Was besonders zu beachten ist, sind die Konstruktoren. Denn so sind die Instanzen überall die gleichen.

Model:
Java:
public class Model {
    // Attribute zum Berechnen des Programmablaufs
    
    
    // Konstruktor
    public Model() {
        
    }
    
    
    // Attribute zum Berechnen des Programmablaufs, get und set Methoden
    public void wertBerechnen() {
        // hier werden Berechnungen ausgeführt
    }
    
    public void wertGeben() {
        // hier werden erechnete Werte gegeben
    }
}

View:
Java:
import javax.swing.*;
import java.awt.*;

public class View extends JPanel {
    // Attribute
    private Model model;
    private Controller controller;
    // Weiter grafische Attribute stehen hier (Komponenten)
    protected Zeichnung zeichnung;
    protected JButton button;
    
    // Konstruktor
    public View(Model m) {
        this.model = m;
        controller = new Controller(this, model);
        // Initialisierung der Komponenten
        zeichnung = new Zeichnung();
        button = new JButton();
        
        // Einstellen der Grafik
        setBounds(0,0,600,600);
        setLayout(null);
        
        add(zeichnung);
        
        button.setText("Knopf");
        button.addActionListener(controller);
        add(button);
        button.setBounds(30, 30, 120, 35);
    }
    

    // Methoden
    public void zeichneAufJComponent(String s) {
        zeichnung.zeichne(s);
    }
    
    
    // Innere Klasse(n)
    /**
     * Es ist durchaus sinnvoll, einen grafischen Komponenten zu erstellen
     * (z.B. wie hier JComponent), der alle Zeichenbefehle ausführt. Denn
     * die Zeichenbefehle sollten nicht direkt von der View ausgeführt
     * werden :
     */
    class Zeichnung extends JComponent {
        // Attribute
        private String bildschirm;
        
        // Konstruktor
        public Zeichnung() {
            // Attribute initialisieren
            bildschirm = "Rot";
            
            // Zeichnung einstellen
            setBounds(0, 0, 600, 600);
        }
        
        
        // Methoden
        /** 
         * >siehe zeichneAufJComponent in Oberklasse
         */
        private void zeichne(String b) {
            bildschirm = b;
            repaint();
        }
        
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D)g;
            
            if(bildschirm.equals("Rot")) {
                g2d.setColor(Color.red);
                g2d.fillRect(200, 200, 150, 150);
            }
            if(bildschirm.equals("Schwarz")) {
                g2d.setColor(Color.black);
                g2d.fillRect(200, 300, 150, 150);
            }
        }
    }
}

Controller:
Java:
import java.awt.event.*;

public class Controller implements ActionListener /*, weitere Listener*/{
    // Attribute
    private Model model;
    private View view;
    
    private boolean klick;
    
    // Konstruktor
    public Controller(View v, Model m) {
        this.view = v;
        this.model = m;
        
        klick = false;
    }
    
    // Methoden
    public void actionPerformed(ActionEvent evt) {
        if(evt.getSource().equals(view.button)) {
            klick = !klick;
            if(klick)  view.zeichneAufJComponent("Schwarz");
            if(!klick) view.zeichneAufJComponent("Rot");
        }
    }
}

Ausführbare Klasse (mit main(...) Methode):
Java:
import javax.swing.*;

public class Application extends JFrame {
    // Attribut(e)
    private View view;

    
    // Konstruktor
    public Application() {
        view = new View(new Model());
        
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setTitle("Model View Controller - Applikation");
        setContentPane(view);
        setVisible(true);
        
        pack();
        setSize(600, 600);
    }
    
    //(Main-)Methode(n)
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new Application();
            }
        });
    }
}

Falls es noch irgendwelche Fragen gibt: Einfach fragen!!!
P.S. Habe ähnlichen Code bereits vorher schon gehabt, um das MVC-Prinzip nen Kumpel zu erklären 🙂
 
Zuletzt bearbeitet:
Wie würde ich jetzt z.B. auf "Knopfdruck" ein neues JPanel laden?

Ganz einfach: Im Controller, beim entsprechenden Knopf:
Java:
view.panelXy.setVisible(false);
view.panelNeu.setVisible(true);

oder habe ich dich falsch verstanden?
 
Zuletzt bearbeitet:
Erstmal danke für die Antworten!
Und GUI-Programmer, ich habe das MVC Modell etwas anders gelöst, das Modell ist Observable und die View ist der Observer.
Trotzdem habe ich eine Frage zu deinem letzten Beitrag, addest du die Panels direkt beim erstmaligen laden? Also dann wirklich nur noch sichtbar und unsichtbar machen?
 
Ja, das habe ich bisher so gemacht. Natürlich geht es auch mit remove(...), ist mir jedoch zu aufwendig.
Was ich dazu sagen muss, ist, dass wenn du sehr viele Komponenten, vor allem JPanels mit weiteren Komponenten hast, solltest du sie mit speziellen Threads laden bzw. intitialisieren. Weiß aber selbst noch nicht so genau wie man das umsetzen kann; bin gerade beim Lesen von: Simple Background Tasks (The Java™ Tutorials > Creating a GUI With JFC/Swing > Concurrency in Swing)

Danach kenn ich mich dann bestimmt damit einigermaßen aus.
 
Zuletzt bearbeitet:
Hallo, nocheinmal: Mit dem CardLayout legst du mehrere Panel an und kannst dann ansteuern, welches davon du angezeigt haben willst...
 

Zurück
Oben