Panel wird nicht angezeigt und Fragen zum CardLayout

DrZaius

Mitglied
Heyho,

Ich möchte eigentlich nur ein Panel anzeigen und ein anderes ausblenden. Ich hab dabei ein kleines Problem, nämlich dass es nicht so passiert wie ich will 😀
Ich poste hier mal ein Stück Code

Java:
public class Gui implements ActionListener{

JPanel panelBlau = new JPanel();
JPanel panelRed = new JPanel();
JButton bBlau = new JButton();
JFrame f = new JFrame();
JButton bRed = new JButton();


public static void main(String[] args){
		
		new Gui();
	}
	
	public Gui(){
		f.setSize(500,500);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		panelBlau.setBackground(Color.blue);
		
		bBlau.setBounds(100,100,100,100);
		bBlau.addActionListener(this);
		panelBlau.add(bBlau);
		panelRed.setBackground(Color.red);
		       
		bRed.setBounds(100,100,100,100);
		bRed.addActionListener(this);
		 
		panelRed.add(bRed);
		panelRed.setVisible(false);
		f.add(panelRed);
		f.add(panelBlau);				
		
		f.setVisible(true);
	}

        @Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource()==bBlau){
			panelBlau.setVisible(false);   	//
			panelRed.setVisible(true);		// <-- Sichtbarkeit wird vertauscht, eigentlich..
			
		}
		if(e.getSource()==bRed){
			panelRed.setVisible(false);
			panelBlau.setVisible(true);
		}
		
	}
	
}

Jetzt ist das Problem, dass nach dem Button von dem blauen Bildschirm das Frame leer wird.
Ich könnte das ganze lösen, indem ich das rote Panel erst im ActionListener adde. Ist das "unschön"?
Bei der Google-Suche bin ich aber auch auf das CardLayout gestoßen.
Kann man, wenn man das CardLayout für ein Panel benutzt, auch noch ein anderes Layout benutzen? (bsp. GridBagLayout) oder kann ich ein Panel mit dem GridBagLayout zu einem Panel mit dem CardLayout hinzufügen?
 
Zuletzt bearbeitet:
Hallo DrZaius,

was meinst du mit "indem ich das rote Panel erst im ActionListener adde"? Das hab ich nicht ganz verstanden. 🙂

Grundsätzlich gilt folgendes:
Ein JFrame ist ein sog. Top-Level Container und leitet von der Klasse Window ab.
Das bedeutet er hat eine Komponente ContentPane, die dann die Oberflächenelemente beherbergt.
Der JFrame ist dann der Root-Knoten für alle darunter liegenenden Komponenten.

Die ContentPane ist eine Instanz der Klasse Container und kann damit auf jede andere Container-Klasse gecastet werden (z.B. JPanel).
Die ContentPane hat das BorderLayout als Default-Layout.

Damit kannst du z.B. dann folgende Sachen machen:
Java:
        JPanel panel = (JPanel) f.getContentPane();
        panel.add(panelRed, BorderLayout.CENTER);
        // oder
        f.getContentPane().add(panelRed, BorderLayout.CENTER);

Natürlich hast du die Möglichkeit dem ContentPane Container ein anderes Layout zuzuweisen.
Jedem Container kann immer nur ein Layout zugewiesen werden.
Aber du kannst natürlich die Container beliebig inneinander schachteln.

Hier ist ein guter Überblick über die verschiedenen Layouts: https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html

VG,
EasyEagle
 
Zuletzt bearbeitet:
Danke für die Antwort, mit dem "im ActionListener adden" meinte ich Folgendes:
Java:
public void actionPerformed(ActionEvent e) {
		if(e.getSource()==bBlau){
			panelBlau.setVisible(false); 
			f.add(panelRed);	
			
		}
		if(e.getSource()==bRed){
			f.remove(panelRed);
			panelBlau.setVisible(true);
		}
		
	}

Damit würde das auch funktionieren. Ist es nun besser ein CardLayout zu verwenden, oder es so zu machen wie o.g. ? Also mit besser meine ich, ob der Code dadurch kürzer und übersichtlicher wird, oder ob es abzuraten ist mit dem CardLayout zu arbeiten.
 
@DrZaius

Mit CardLayout kenne ich mich nicht aus. Aber zu deinem aktuellen Problem. Wie schon gesagt wurde hat das Frame (genauer gesagt das ContentPane) das BorderLayout. Du überschreibst dir dein gerade gesetztes panelRed mit dem panelBlau.
Java:
f.add(panelRed);
f.add(panelBlau);

Denn wenn nichts weiter angegeben wird, werden Components an BorderLayout.CENTER gesetzt. Und da kann es halt immer nur ein Component geben. Du könntest z.B. folgendes machen:
Java:
f.add(panelRed, BorderLayout.WEST);
f.add(panelBlau, BorderLayout.EAST);

Wenn dir das nicht gefällt, kannst du entweder dem JFrame(contentPane) ein anderes Layout verpassen
Code:
f.setLayout(new WasAuchImmerManager());
oder du schaffst dir ein JPanel mit favorisierten LayoutManager und setzt das ins BorderLayout.CENTER des JFrames.
Java:
JPanel p = new JPanel();
p.setLayout(new WasAuchImmerManager());

//...panelRed und panelBlau dem "p" hinzufügen

f.add(p, BorderLayout.CENTER); //ist wie gesagt dasselbe wie: f.add(p);
 
Zuletzt bearbeitet von einem Moderator:
Also die Lösung mit "im ActionListener adden" halte ich für unübersichtlich.
Ich denke das CardLayout ist in dem Fall genau das Richtige.

VG
 
@X5-599
Das Prinzip verstehe und kenne ich schon, aber das Problem war ja, dass die Panels nacheinander angezeigt werden sollten. Aber trotzdem danke. Ich denk, dass ich mich jetzt erstmal in das CardLayout einarbeite, so wie EasyEagle sagt.
 
Die ContentPane des JFrame ist keine Instanz der Klasse Container sondern eine Instanz der Klasse JPanel, was dir die Anweisung System.out.println(getContentPane().getClass()); verrät, und kann damit sicherlich nicht in jede andere Container-Klasse (das wäre dann alles was sich von Container ableitet?) gecastet werden sondern nur in JPanel und dessen Superklassen. hier meine Idee bezüglich der Panels:

Java:
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class Gui implements ActionListener {

	JFrame frame = new JFrame();
	JPanel panelBlau = new JPanel();
	JPanel panelRed = new JPanel();
	JButton buttonBlau = new JButton();
	JButton buttonRed = new JButton();
	CardLayout cardLayout = new CardLayout();
	JPanel holder = new JPanel(cardLayout);

	public Gui() {
		frame.setSize(500, 500);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);

		panelBlau.setLayout(null);
		buttonBlau.setBounds(100, 100, 100, 100);
		panelBlau.setBackground(Color.blue);
		buttonBlau.addActionListener(this);
		panelBlau.add(buttonBlau);

		panelRed.setLayout(null);
		buttonRed.setBounds(100, 100, 100, 100);
		panelRed.setBackground(Color.red);
		buttonRed.addActionListener(this);
		panelRed.add(buttonRed);

		holder.add(panelBlau);
		holder.add(panelRed);
		cardLayout.addLayoutComponent(panelBlau, "blau");
		cardLayout.addLayoutComponent(panelRed, "rot");

		frame.add(holder);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == buttonBlau) {
			cardLayout.show(holder, "rot");
		}
		if (e.getSource() == buttonRed) {
			cardLayout.show(holder, "blau");
		}
	}

	public static void main(String[] args) {
		new Gui();
	}

}
 

Neue Themen


Zurück
Oben