Wie Vorgehen bei fundamentaler Veränderung des Layouts während des Programmablaufs?

Rufus.Mueller

Bekanntes Mitglied
Das Programm das ich schreibe verläuft linear-sequentiell, d.h. es gibt einen "Startbildschirm" mit einem "Weiter"-Button. Wenn weiter gedrückt wird, soll sich die Anzeige und daher auch das Layout gravierend ändern.


0. Ansicht:
Der JFrame enthält ein Panel, nichts weiter.

1. Ansicht: In der Mitte ist ein Panel und untendrunter zwei Buttons. Das löse ich mit BorderLayout (Das Pane kommt nach CENTER) im JFrame und BoxLayout auf der SOUTH Seite des JFrames, wo die Buttons rein kommen

2. Ansicht: Es gibt wieder ein Panel in der Mitte. Untendrunter ist nur noch ein Button. Aber ein anderer Button als bei der ersten Ansicht.

3. Ansicht: Links ist ein JPanel und rechts sind mehrere editierbare Textfelder. Eventuell sind JPanel und die editierbaren Textfelder auch untereinander angeordnet.


Es muss mehrmals zwischen den verschiedenen Ansichten hin- und her geschaltet werden, es ist auch nicht auszuschließen, dass noch ein oder zwei weitere Ansichten hinzu kommen.


Es fallen mir verschiedene Lösungsmöglichkeiten ein, ich bin mir aber nicht sicher welches die beste ist:


Lösung 1: Für jede Ansicht eine eigene Klasse als Subklasse von JFrame schreiben. Bei einem Wechsel der Ansicht wird das erste Fenster geschlossen und ein frisches aufgemacht (geht das so schnell, dass es der Anwender nicht merkt?).

Lösung 2: Soviele Panels wie es Ansichten gibt in das JFrame legen und den Panels jeweils ein anderes Layout geben. Die gerade nicht benötigten Ansicht sind dabei auf visible(false) geschaltet.
 
C

Camino

Gast
Ich bin mir nicht sicher: Kann es der Übersicht halber sinnvoll sein, für jede card eine separate Klasse anzulegen?
Ja, das kann manchmal übersichtlicher sein und helfen. Ich hab z.B. in meiner Anwendung für jede Card eine Klasse (abgeleitet von JPanel) erstellt, diese dann dem CardLayout hinzugefügt und kann dann problemlos hin und her wechseln.
 

Rufus.Mueller

Bekanntes Mitglied
So habe ich es auch gemacht. Nur problemlos ist es bei mir, wie nicht anders zu erwarten, nicht! ;)

Ich habe eine Klasse Window. Ich erzeuge mit der main-Methode ein Window und rufe die Methode starte() auf window auf. Die Methode starte() habe ich in drei Varianten ausprobiert (einmal soll sie card1 setzen, einmal card2 , es passiert immer etwas ähnliches bizarres.

Variante 1 (card 1 wird aufgerufen)
=========================
-in neun von zehn Programmstarts wird card3.CENTER anstelle von card1 angezeigt
-in einem von zehn Programmstarts wird card1 richtigerweise angezeigt, allerdings enthält sie zusätzlich die Komponenten von card3

Variante 2 (card 2 wird aufgerufen)
=========================
-in neun von zehn Programmstarts wird card3.CENTER anstelle von card2 angezeigt
-in einem von zehn Programmstarts wird card2 richtigerweise angezeigt, allerdings enthält sie zusätzlich die Komponenten von card3

Variante 3 (card 3 wird aufgerufen)
=========================
-in neun von zehn Programmstarts wird card3.CENTER angezeigt, anstelle card3.
-in einem von zehn Programmstarts wird card3 vollständig angezeigt, allerdings ist der Bereich den ich auf .SOUTH gelegt habe, in .NORTH zu finden.


Wenn ich starte() gar nicht aufrufe und nur ein Fester erzeuge, passiert das gleiche wie in Variante 1. ???:L

Java:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.Font;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;


public class Window extends JFrame {
	

	Card1 panelCard1;
	Card2 panelCard2;
	Card3 panelCard3;
	Card4 panelCard4;
	JPanel cards;
	CardLayout cardLayout;
	
	

	//Konstruktor
	public Window(){
		this.setLayout(new BorderLayout());
		
		
		//*** Fenster ***//
		
		//Window erzeugen
		this.setExtendedState(JFrame.MAXIMIZED_BOTH);
		this.setVisible(true);
		this.setBackground(Color.YELLOW);		
		
		//Fenster WIRKLICH auf Vollbild stellen
		setSize( Toolkit.getDefaultToolkit().getScreenSize() ); 
	    GraphicsDevice device; 
	    device=GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0]; 
	    device.setFullScreenWindow(this); 
	    device.setDisplayMode(new DisplayMode(1024,768,16,0)); 

		//Window schließbar machen und Menu setzen
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		
		
		//***cardLayout***//
		
		//CardLayout
		cards = new JPanel (new CardLayout());
		cardLayout = (CardLayout)(cards.getLayout());
		cards.setBackground(Color.BLACK);
		this.add(cards);
		panelCard1 = new Card1(this);
		panelCard2 = new Card2(this);
		panelCard3 = new Card3(this);
	    cards.add(panelCard1, "Start");
	    cards.add(panelCard2, "Erklaerung");
	    cards.add(panelCard3, "CorsiAufgabe");
	    
	}
	
	//Methodenteil
	
	public void starten(){
		this.cardLayout.show(cards, "CorsiAufgabe");
	}

}

Java:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class Card3 extends JPanel {
	
	//Deklarationsteil

	boolean eingabeBeendet;
	JPanel suedpanel;
	JLabel moglerMeldung;
	CorsiBloecke corsiBloecke;
	Window window;
	JLabel rueckmeldungenRichtig;
	JLabel rueckmeldungenFalsch;
	boolean naechsteSequenzAngefordert;
	JButton buttonNaechsteSequenzStarten;
	JButton buttonEingabeBeenden;
	
	
	
	public Card3(Window window) {
		this.window=window;
		
		naechsteSequenzAngefordert=false;
	
		//Buttons erzeugen und Größe einstellen
		buttonEingabeBeenden = new JButton("Eingabe beenden");
		buttonEingabeBeenden.setPreferredSize(new Dimension(140, 40));
		buttonNaechsteSequenzStarten = new JButton("Sequenz starten");
		buttonNaechsteSequenzStarten.setPreferredSize(new Dimension(140, 40));
		
		//Panels erzeugen und adden für Layout
		suedpanel=new JPanel();
		suedpanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 10, 0));
		suedpanel.add(buttonNaechsteSequenzStarten);
		suedpanel.add(Box.createRigidArea(new Dimension(70, 0)));
		suedpanel.add(buttonEingabeBeenden);
		suedpanel.setBackground(Color.BLACK);
		this.add(suedpanel, BorderLayout.SOUTH);
		suedpanel.add(buttonNaechsteSequenzStarten);
		suedpanel.add(buttonEingabeBeenden);

		buttonEingabeBeenden.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg) {
				eingabeBeendet=true;
				Card3.this.buttonEingabeBeenden.setVisible(false); 
				Card3.this.buttonNaechsteSequenzStarten.setVisible(true);
			};
		});

	
		buttonNaechsteSequenzStarten.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg) {
				naechsteSequenzAngefordert=true;	
				Card3.this.buttonNaechsteSequenzStarten.setVisible(false); 
				Card3.this.buttonEingabeBeenden.setVisible(true);
			
			};
		});

		
		//***Label für Rückmeldungen (richtig vs. falsch) erzeugen und einstellen
		//Label für Rückmeldungen "richtig
		rueckmeldungenRichtig = new JLabel();
		rueckmeldungenRichtig.setVisible(false);
		rueckmeldungenRichtig.setForeground(Color.BLACK);
		rueckmeldungenRichtig.setFont(new Font("Dialog", 0, 50));
		rueckmeldungenRichtig.setOpaque(true);
		rueckmeldungenRichtig.setBounds(400,200,300,100);
		rueckmeldungenRichtig.setText("Richtig!");
		this.add(rueckmeldungenRichtig);
	
		rueckmeldungenFalsch = new JLabel();
		rueckmeldungenFalsch.setVisible(false);
		rueckmeldungenFalsch.setForeground(Color.BLACK);
		rueckmeldungenFalsch.setFont(new Font("Dialog", 0, 50));
		rueckmeldungenFalsch.setOpaque(true);
		rueckmeldungenFalsch.setBounds(400,200,300,100);
		rueckmeldungenFalsch.setText("Falsch!");
		this.add(rueckmeldungenFalsch);
	
	
	
		//Corsi-Blöcke machen und add-en
		corsiBloecke = new CorsiBloecke();
		Card3.this.window.add(corsiBloecke, BorderLayout.CENTER);
		Card3.this.window.validate();
	
	
		//Label für Mogler-Meldung 
		moglerMeldung = new JLabel("Sie konnten sich eine Sequenzlänge von zwei nicht merken. Bitte wenden Sie sich an den Versuchsleiter.");
		moglerMeldung.setVisible(false);
		moglerMeldung.setOpaque(false);
		moglerMeldung.setFont(new Font("Dialog", 0, 15));
		moglerMeldung.setBounds(10,10,800,500);
		Card3.this.window.add(moglerMeldung);  
	}
	
	
	
		//***Methodenteil***//
		
		//starten den Versuch mit Versuchsaufklärung

		
		//rueckmeldungenRichtig einblenden
		public void einblendenRueckmeldungenRichtig() {
			this.rueckmeldungenRichtig.setVisible(true);
		}
		
		//rueckmeldungenRichtig ausblenden 
		public void ausblendenRueckmeldungenRichtig() {
			this.rueckmeldungenRichtig.setVisible(false);
		}
		
		//rueckmeldungenFalsch sichtbar machen
		public void zeigenRueckmeldungenFalsch() {
			this.rueckmeldungenFalsch.setVisible(true);
		}
			
		//rueckmeldungenFalsch ausblenden 
		public void ausblendenRueckmeldungenFalsch() {
			this.rueckmeldungenFalsch.setVisible(false);
		}	
	
		
		
	
		
	
		
		//starten den Versuch mit Versuchsaufklärung
		public void weiter(){
			Card3.this.window.cardLayout.show(Card3.this.window.cards, "CorsiAufgabe");
		}
		
		
		
		//setzt das flag eingabeBeendet auf false zurück
		public void eingabeBeendetFalseSetzen(){
			this.eingabeBeendet = false;
		}
		
		//gibt den Wert der booleanen Variablen 
		public boolean statusEingabeBeendet(){
			return this.eingabeBeendet;
		}
		
		//gibt Status "naechsteSequenzAngefordert"
		public boolean statusNaechsteSequenzAngefordert() {
			return naechsteSequenzAngefordert;
		}
		
		//Mogler-Meldung einblenden
		public void moglerMeldung() {
		this.moglerMeldung.setVisible(true);
		this.corsiBloecke.setVisible(false);
		this.buttonNaechsteSequenzStarten.setVisible(false);
		this.buttonEingabeBeenden.setVisible(false);
		this.ausblendenRueckmeldungenFalsch();
		
		}
}
 
C

Camino

Gast
Zuerst einmal würde ich
[JAVA=38]this.setVisible(true);[/code]
in deinem Window als letztes aufrufen. Du hast das viel zu weit oben schon drin.

Das sieht auch etwas komisch/umständlich aus:
Java:
cards = new JPanel (new CardLayout());
cardLayout = (CardLayout)(cards.getLayout());

Mach doch lieber so:
Java:
cardLayout = new CardLayout();
cards = new JPanel(cardLayout);

Den Rest muss ich dann mal noch weiter anschauen...

OK, keine Ahnung, ob das eine wichtige Rolle spielt, aber wegen der Übersichtlichkeit würde ich
[JAVA=58]this.add(cards);[/code]
auch weiter nach unten verschieben, also das JPanel dem JFrame erst zum Schluss hinzufügen, wenn alle Panels zum CardLayout hinzugefügt worden sind. Und danach zum Schluss dann dem JFrame setVisible(true) setzen.
 
Zuletzt bearbeitet von einem Moderator:

Rufus.Mueller

Bekanntes Mitglied
Habe die von Dir vorgeschlagenen Änderungen durchgeführt.

Alle Varianten
==========
Mein Fenster ist ja ein "echtes" Vollbild. Bisher konnte ich es aber schließen, wenn ich auf die Stelle gedrückt habe wo normalerweise das X steht. Das geht jetzt nicht mehr, ich muss es jetzt erst mit Alt+Umschalt verkleinern bevor ich es schließen kann.

Variante 1
=======
Es wird nun ausschließlich card3.CENTER angezeigt.

Variante 2
=======
Unverändert.

Variante 3
=======
Der Fall, dass zusätzlich zu dem angezeigten card3.CENTER der Bereich der eigentlich in SOUTH stehen sollte statt gar nicht in NORTH angezeigt wird, tritt nun seltener auf (vielleicht in 1/20 aller Fälle). Dafür tritt nun auch hier der Fall auf, dass card1.CENTER versehen mit den Komponenten von card3 auftaucht.
 
Zuletzt bearbeitet:
C

Camino

Gast
Keine Ahnung, was du da machst, aber wo hast du deinem Card3 denn ein BorderLayout verpasst?
Wenn du dann
[JAVA=50]this.add(suedpanel, BorderLayout.SOUTH);[/code]
das suedpanel so zuweisen möchtest, kann das ja nicht klappen...
 
C

Camino

Gast
Es ist ja auch nicht nur das suedpanel, die anderen Komponenten fügst du ja auch mit add dem Panel hinzu. Da musst du ja auch angeben, in welchen Bereich die eingefügt werden sollen. Wenn du das mit dem BorderLayout und den richtigen add-Methoden geändert hast, kannst du ja nochmal die Klasse Card3 hier posten, dann kann man sich das nochmal anschauen.

Ergänzung:
Auch das sieht etwas seltsam aus:
Java:
buttonEingabeBeenden.addActionListener(new ActionListener() {
 
            @Override
            public void actionPerformed(ActionEvent arg) {
                eingabeBeendet=true;
                Card3.this.buttonEingabeBeenden.setVisible(false); 
                Card3.this.buttonNaechsteSequenzStarten.setVisible(true);
            };
        });

Warum machst du das nicht so:
Java:
buttonEingabeBeenden.addActionListener(new ActionListener() {
 
            @Override
            public void actionPerformed(ActionEvent arg) {
                eingabeBeendet=true;
                buttonEingabeBeenden.setVisible(false); 
                buttonNaechsteSequenzStarten.setVisible(true);
            };
        });
Die Buttons hast du doch als Objektvariablen angelegt...
 
Zuletzt bearbeitet von einem Moderator:

Rufus.Mueller

Bekanntes Mitglied
Ich bin mir nicht sicher, ob ich Dich richtig verstehe. card3 hatte kein BorderLayout, sondern das default-Layout. Das habe ich jetzt geändert, indem ich das BorderLayout explizit gesetzt habe. In card3 verwenden suedpanel und corsibloecke das BorderLayout, da musste ich nichts ändern, da diese das eh schon so eingestellt waren, dass sie es benutzen. In card2 hatte ich auch vergessen das Layout zu setzen, dadurch sieht card2 jetzt anders aus, hat aber wohl nichts mit dem eigentlichen Problem zu tun. Die add-Methoden waren, so wie ich es sehe, richtig.

Unten stehend die Klassen mit denen ich aktuell arbeite.

Java:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class Card3 extends JPanel {
	
	//Deklarationsteil

	boolean eingabeBeendet;
	JPanel suedpanel;
	JLabel moglerMeldung;
	CorsiBloecke corsiBloecke;
	Window window;
	JLabel rueckmeldungenRichtig;
	JLabel rueckmeldungenFalsch;
	boolean naechsteSequenzAngefordert;
	JButton buttonNaechsteSequenzStarten;
	JButton buttonEingabeBeenden;
	
	
	
	public Card3(Window window) {
		this.window=window;
		
		naechsteSequenzAngefordert=false;
		this.setLayout(new BorderLayout());
	
		//Buttons erzeugen und Größe einstellen
		buttonEingabeBeenden = new JButton("Eingabe beenden");
		buttonEingabeBeenden.setPreferredSize(new Dimension(140, 40));
		buttonNaechsteSequenzStarten = new JButton("Sequenz starten");
		buttonNaechsteSequenzStarten.setPreferredSize(new Dimension(140, 40));
		
		//Panels erzeugen und adden für Layout
		suedpanel=new JPanel();
		suedpanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 10, 0));
		suedpanel.add(buttonNaechsteSequenzStarten);
		suedpanel.add(Box.createRigidArea(new Dimension(70, 0)));
		suedpanel.add(buttonEingabeBeenden);
		suedpanel.setBackground(Color.ORANGE);
		this.add(suedpanel, BorderLayout.SOUTH);
		suedpanel.add(buttonNaechsteSequenzStarten);
		suedpanel.add(buttonEingabeBeenden);

		buttonEingabeBeenden.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg) {
				eingabeBeendet=true;
				Card3.this.buttonEingabeBeenden.setVisible(false); 
				Card3.this.buttonNaechsteSequenzStarten.setVisible(true);
			};
		});

	
		buttonNaechsteSequenzStarten.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg) {
				naechsteSequenzAngefordert=true;	
				Card3.this.buttonNaechsteSequenzStarten.setVisible(false); 
				Card3.this.buttonEingabeBeenden.setVisible(true);
			
			};
		});

		
		//***Label für Rückmeldungen (richtig vs. falsch) erzeugen und einstellen
		//Label für Rückmeldungen "richtig
		rueckmeldungenRichtig = new JLabel();
		rueckmeldungenRichtig.setVisible(false);
		rueckmeldungenRichtig.setForeground(Color.BLACK);
		rueckmeldungenRichtig.setFont(new Font("Dialog", 0, 50));
		rueckmeldungenRichtig.setOpaque(true);
		rueckmeldungenRichtig.setBounds(400,200,300,100);
		rueckmeldungenRichtig.setText("Richtig!");
		this.add(rueckmeldungenRichtig);
	
		rueckmeldungenFalsch = new JLabel();
		rueckmeldungenFalsch.setVisible(false);
		rueckmeldungenFalsch.setForeground(Color.BLACK);
		rueckmeldungenFalsch.setFont(new Font("Dialog", 0, 50));
		rueckmeldungenFalsch.setOpaque(true);
		rueckmeldungenFalsch.setBounds(400,200,300,100);
		rueckmeldungenFalsch.setText("Falsch!");
		this.add(rueckmeldungenFalsch);
	
	
	
		//Corsi-Blöcke machen und add-en
		corsiBloecke = new CorsiBloecke();
		Card3.this.window.add(corsiBloecke, BorderLayout.CENTER);
		Card3.this.window.validate();
	
	
		//Label für Mogler-Meldung 
		moglerMeldung = new JLabel("Sie konnten sich eine Sequenzlänge von zwei nicht merken. Bitte wenden Sie sich an den Versuchsleiter.");
		moglerMeldung.setVisible(false);
		moglerMeldung.setOpaque(false);
		moglerMeldung.setFont(new Font("Dialog", 0, 15));
		moglerMeldung.setBounds(10,10,800,500);
		Card3.this.window.add(moglerMeldung);  
	}
	
	
	
		//***Methodenteil***//
		
		//starten den Versuch mit Versuchsaufklärung

		
		//rueckmeldungenRichtig einblenden
		public void einblendenRueckmeldungenRichtig() {
			this.rueckmeldungenRichtig.setVisible(true);
		}
		
		//rueckmeldungenRichtig ausblenden 
		public void ausblendenRueckmeldungenRichtig() {
			this.rueckmeldungenRichtig.setVisible(false);
		}
		
		//rueckmeldungenFalsch sichtbar machen
		public void zeigenRueckmeldungenFalsch() {
			this.rueckmeldungenFalsch.setVisible(true);
		}
			
		//rueckmeldungenFalsch ausblenden 
		public void ausblendenRueckmeldungenFalsch() {
			this.rueckmeldungenFalsch.setVisible(false);
		}	
	
		
		
	
		
	
		
		//starten den Versuch mit Versuchsaufklärung
		public void weiter(){
			Card3.this.window.cardLayout.show(Card3.this.window.cards, "CorsiAufgabe");
		}
		
		
		
		//setzt das flag eingabeBeendet auf false zurück
		public void eingabeBeendetFalseSetzen(){
			this.eingabeBeendet = false;
		}
		
		//gibt den Wert der booleanen Variablen 
		public boolean statusEingabeBeendet(){
			return this.eingabeBeendet;
		}
		
		//gibt Status "naechsteSequenzAngefordert"
		public boolean statusNaechsteSequenzAngefordert() {
			return naechsteSequenzAngefordert;
		}
		
		//Mogler-Meldung einblenden
		public void moglerMeldung() {
		this.moglerMeldung.setVisible(true);
		this.corsiBloecke.setVisible(false);
		this.buttonNaechsteSequenzStarten.setVisible(false);
		this.buttonEingabeBeenden.setVisible(false);
		this.ausblendenRueckmeldungenFalsch();
		
		}
}


Java:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.Font;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;


public class Window extends JFrame {
	

	Card1 panelCard1;
	Card2 panelCard2;
	Card3 panelCard3;
	JPanel cards;
	CardLayout cardLayout;
	
	

	//Konstruktor
	public Window(){
		this.setLayout(new BorderLayout());
		
		
		//*** Fenster ***//
		
		//Window erzeugen
		this.setExtendedState(JFrame.MAXIMIZED_BOTH);
		this.setBackground(Color.YELLOW);		
		
	/*	//Fenster WIRKLICH auf Vollbild stellen
		setSize( Toolkit.getDefaultToolkit().getScreenSize() ); 
	    GraphicsDevice device; 
	    device=GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0]; 
	    device.setFullScreenWindow(this); 
	    device.setDisplayMode(new DisplayMode(1024,768,16,0));  */

		//Window schließbar machen und Menu setzen
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		
		
		//***cardLayout***//
		
		//CardLayout
		cardLayout = new CardLayout();
		cards = new JPanel(cardLayout);

		
		panelCard1 = new Card1(this);
		panelCard2 = new Card2(this);
		panelCard3 = new Card3(this);
	//	cards.add(panelCard1, "Start");
	    cards.add(panelCard2, "Erklaerung");
	   cards.add(panelCard3, "CorsiAufgabe");
	    
	    this.add(cards);
	    this.setVisible(true);
	    
	}
	
	//Methodenteil
	
	public void starten(){
	//	this.cardLayout.show(cards, "CorsiAufgabe");
	}

}
 
C

Camino

Gast
In Card3 fügst du auch noch 2 Label hinzu (mit add), ohne den Bereich im BorderLayout anzugeben...
 

Rufus.Mueller

Bekanntes Mitglied
Ah, okay. Die meintest Du.

Java:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class Card3 extends JPanel {
	
	//Deklarationsteil

	boolean eingabeBeendet;
	JPanel suedpanel;
	JLabel moglerMeldung;
	CorsiBloecke corsiBloecke;
	Window window;
	JLabel rueckmeldungenRichtig;
	JLabel rueckmeldungenFalsch;
	boolean naechsteSequenzAngefordert;
	JButton buttonNaechsteSequenzStarten;
	JButton buttonEingabeBeenden;
	
	
	
	public Card3(Window window) {
		this.window=window;
		
		naechsteSequenzAngefordert=false;
		this.setLayout(new BorderLayout());
	
		//Buttons erzeugen und Größe einstellen
		buttonEingabeBeenden = new JButton("Eingabe beenden");
		buttonEingabeBeenden.setPreferredSize(new Dimension(140, 40));
		buttonNaechsteSequenzStarten = new JButton("Sequenz starten");
		buttonNaechsteSequenzStarten.setPreferredSize(new Dimension(140, 40));
		
		//Panels erzeugen und adden für Layout
		suedpanel=new JPanel();
		suedpanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 10, 0));
		suedpanel.add(buttonNaechsteSequenzStarten);
		suedpanel.add(Box.createRigidArea(new Dimension(70, 0)));
		suedpanel.add(buttonEingabeBeenden);
		suedpanel.setBackground(Color.ORANGE);
		this.add(suedpanel, BorderLayout.SOUTH);
		suedpanel.add(buttonNaechsteSequenzStarten);
		suedpanel.add(buttonEingabeBeenden);

		buttonEingabeBeenden.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg) {
				eingabeBeendet=true;
				Card3.this.buttonEingabeBeenden.setVisible(false); 
				Card3.this.buttonNaechsteSequenzStarten.setVisible(true);
			};
		});

	
		buttonNaechsteSequenzStarten.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg) {
				naechsteSequenzAngefordert=true;	
				Card3.this.buttonNaechsteSequenzStarten.setVisible(false); 
				Card3.this.buttonEingabeBeenden.setVisible(true);
			
			};
		});

		
		//***Label für Rückmeldungen (richtig vs. falsch) erzeugen und einstellen
		//Label für Rückmeldungen "richtig
		rueckmeldungenRichtig = new JLabel();
		rueckmeldungenRichtig.setVisible(false);
		rueckmeldungenRichtig.setForeground(Color.BLACK);
		rueckmeldungenRichtig.setFont(new Font("Dialog", 0, 50));
		rueckmeldungenRichtig.setOpaque(true);
		rueckmeldungenRichtig.setBounds(400,200,300,100);
		rueckmeldungenRichtig.setText("Richtig!");
		this.add(rueckmeldungenRichtig, BorderLayout.CENTER);
	
		rueckmeldungenFalsch = new JLabel();
		rueckmeldungenFalsch.setVisible(false);
		rueckmeldungenFalsch.setForeground(Color.BLACK);
		rueckmeldungenFalsch.setFont(new Font("Dialog", 0, 50));
		rueckmeldungenFalsch.setOpaque(true);
		rueckmeldungenFalsch.setBounds(400,200,300,100);
		rueckmeldungenFalsch.setText("Falsch!");
		this.add(rueckmeldungenFalsch, BorderLayout.CENTER);
	
	
	
		//Corsi-Blöcke machen und add-en
		corsiBloecke = new CorsiBloecke();
		Card3.this.window.add(corsiBloecke, BorderLayout.CENTER);
		Card3.this.window.validate();
	
	
		//Label für Mogler-Meldung 
		moglerMeldung = new JLabel("Sie konnten sich eine Sequenzlänge von zwei nicht merken. Bitte wenden Sie sich an den Versuchsleiter.");
		moglerMeldung.setVisible(false);
		moglerMeldung.setOpaque(false);
		moglerMeldung.setFont(new Font("Dialog", 0, 15));
		moglerMeldung.setBounds(10,10,800,500);
		Card3.this.window.add(moglerMeldung, BorderLayout.CENTER);  
	}
	
	
	
		//***Methodenteil***//
		
		//starten den Versuch mit Versuchsaufklärung

		
		//rueckmeldungenRichtig einblenden
		public void einblendenRueckmeldungenRichtig() {
			this.rueckmeldungenRichtig.setVisible(true);
		}
		
		//rueckmeldungenRichtig ausblenden 
		public void ausblendenRueckmeldungenRichtig() {
			this.rueckmeldungenRichtig.setVisible(false);
		}
		
		//rueckmeldungenFalsch sichtbar machen
		public void zeigenRueckmeldungenFalsch() {
			this.rueckmeldungenFalsch.setVisible(true);
		}
			
		//rueckmeldungenFalsch ausblenden 
		public void ausblendenRueckmeldungenFalsch() {
			this.rueckmeldungenFalsch.setVisible(false);
		}	
	
		
		
	
		
	
		
		//starten den Versuch mit Versuchsaufklärung
		public void weiter(){
			Card3.this.window.cardLayout.show(Card3.this.window.cards, "CorsiAufgabe");
		}
		
		
		
		//setzt das flag eingabeBeendet auf false zurück
		public void eingabeBeendetFalseSetzen(){
			this.eingabeBeendet = false;
		}
		
		//gibt den Wert der booleanen Variablen 
		public boolean statusEingabeBeendet(){
			return this.eingabeBeendet;
		}
		
		//gibt Status "naechsteSequenzAngefordert"
		public boolean statusNaechsteSequenzAngefordert() {
			return naechsteSequenzAngefordert;
		}
		
		//Mogler-Meldung einblenden
		public void moglerMeldung() {
		this.moglerMeldung.setVisible(true);
		this.corsiBloecke.setVisible(false);
		this.buttonNaechsteSequenzStarten.setVisible(false);
		this.buttonEingabeBeenden.setVisible(false);
		this.ausblendenRueckmeldungenFalsch();
		
		}
}
 
C

Camino

Gast
In card3 verwenden suedpanel und corsibloecke das BorderLayout, da musste ich nichts ändern, da diese das eh schon so eingestellt waren, dass sie es benutzen.
Hmm, suedpanel wird dem SOUTH-Bereich von card3 zugewiesen. Aber was soll das mit corsibloecke werden:
Java:
//Corsi-Blöcke machen und add-en
corsiBloecke = new CorsiBloecke();
Card3.this.window.add(corsiBloecke, BorderLayout.CENTER);
Card3.this.window.validate();
Die Schreibweise ist etwas ungewöhnlich, aber kann sein, dass du die corsiBloecke dem window in den CENTER-Bereich zuweist?
 
C

Camino

Gast
Ah, okay. Die meintest Du.
Ja, aber wenn du beide dem CENTER-Bereich zuweist, wird nur das letzte davon dort eingefügt werden. Du kannst nur eine Komponente pro Bereich beim BorderLayout einfügen. Das heisst, wenn du mehrere Komponenten dort drinhaben möchtest, musst du die erst auf ein Panel packen und dies dann dort in den Bereich einfügen, also LayoutManager verschachteln.
 
Zuletzt bearbeitet von einem Moderator:

Rufus.Mueller

Bekanntes Mitglied
Hier lag offenbar ein Großteil des Hasens im Pfeffer! Diese "seltsame" Formulierung hatte ich ursprünglich eingeführt um von den ActionPerformed-Methoden der Buttons der Panels auf die Panels zugreifen zu können. Habe diese Schreibweise jetzt überall beseitigt wo sie nicht unbedingt erforderlich ist.

Es wird jetzt immer die richtige Card angezeigt. Die Cards selbst enthalten Buttons mit denen ich immer eine Card weiterschalten kann. Das funktioniert soweit auch. Jetzt kommt der Wermutstropfen: In Card3 wird corsiBloecke nicht in .CENTER angezeigt, in .CENTER ist einfach nur der nackte Hintergrund des Panels zu sehen. Um auszuschließen das hier noch ein Fehler in der Schreibweise vorliegt, habe ich mal einen Testbutton instanziiert. Es ist mir gelungen den auf jedes der Felder des BorderLayouts zu setzen, AUßER auf CENTER. In CENTER lässt sich keine Komponente reinsetzen.

Java:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class Card3 extends JPanel {
	
	//Deklarationsteil

	boolean eingabeBeendet;
	JPanel suedpanel;
	JLabel moglerMeldung;
	CorsiBloecke corsiBloecke;
	Window window;
	JLabel rueckmeldungenRichtig;
	JLabel rueckmeldungenFalsch;
	boolean naechsteSequenzAngefordert;
	JButton buttonNaechsteSequenzStarten;
	JButton buttonEingabeBeenden;
	
	
	
	public Card3(Window window) {
		this.window=window;
		
		naechsteSequenzAngefordert=false;
		this.setLayout(new BorderLayout());
	
		//Buttons erzeugen und Größe einstellen
		buttonEingabeBeenden = new JButton("Eingabe beenden");
		buttonEingabeBeenden.setPreferredSize(new Dimension(140, 40));
		buttonNaechsteSequenzStarten = new JButton("Sequenz starten");
		buttonNaechsteSequenzStarten.setPreferredSize(new Dimension(140, 40));
		
		//Panels erzeugen und adden für Layout
		suedpanel=new JPanel();
		suedpanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 10, 0));
		suedpanel.add(buttonNaechsteSequenzStarten);
		suedpanel.add(Box.createRigidArea(new Dimension(70, 0)));
		suedpanel.add(buttonEingabeBeenden);
		suedpanel.setBackground(Color.ORANGE);
		this.add(suedpanel, BorderLayout.SOUTH);
		suedpanel.add(buttonNaechsteSequenzStarten);
		suedpanel.add(buttonEingabeBeenden);

		buttonEingabeBeenden.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg) {
				eingabeBeendet=true;
				Card3.this.buttonEingabeBeenden.setVisible(false); 
				Card3.this.buttonNaechsteSequenzStarten.setVisible(true);
			};
		});

	
		buttonNaechsteSequenzStarten.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg) {
				naechsteSequenzAngefordert=true;	
				Card3.this.buttonNaechsteSequenzStarten.setVisible(false); 
				Card3.this.buttonEingabeBeenden.setVisible(true);
			
			};
		});

		
		//***Label für Rückmeldungen (richtig vs. falsch) erzeugen und einstellen
		//Label für Rückmeldungen "richtig
		rueckmeldungenRichtig = new JLabel();
		rueckmeldungenRichtig.setVisible(false);
		rueckmeldungenRichtig.setForeground(Color.BLACK);
		rueckmeldungenRichtig.setFont(new Font("Dialog", 0, 50));
		rueckmeldungenRichtig.setOpaque(true);
		rueckmeldungenRichtig.setBounds(400,200,300,100);
		rueckmeldungenRichtig.setText("Richtig!");
		this.add(rueckmeldungenRichtig, BorderLayout.CENTER);
	
		rueckmeldungenFalsch = new JLabel();
		rueckmeldungenFalsch.setVisible(false);
		rueckmeldungenFalsch.setForeground(Color.BLACK);
		rueckmeldungenFalsch.setFont(new Font("Dialog", 0, 50));
		rueckmeldungenFalsch.setOpaque(true);
		rueckmeldungenFalsch.setBounds(400,200,300,100);
		rueckmeldungenFalsch.setText("Falsch!");
		this.add(rueckmeldungenFalsch, BorderLayout.CENTER);
	
	
		
//		JButton gammel=new JButton("bowe");
//		this.add(gammel, BorderLayout.CENTER);
		
		
	
		//Corsi-Blöcke machen und add-en
		corsiBloecke = new CorsiBloecke();
		this.add(corsiBloecke, BorderLayout.CENTER);
		this.window.validate();
	
	
		//Label für Mogler-Meldung 
		moglerMeldung = new JLabel("Sie konnten sich eine Sequenzlänge von zwei nicht merken. Bitte wenden Sie sich an den Versuchsleiter.");
		moglerMeldung.setVisible(false);
		moglerMeldung.setOpaque(false);
		moglerMeldung.setFont(new Font("Dialog", 0, 15));
		moglerMeldung.setBounds(10,10,800,500);
		this.add(moglerMeldung, BorderLayout.CENTER);  
	}
	
	
	
		//***Methodenteil***//
		
		//starten den Versuch mit Versuchsaufklärung

		
		//rueckmeldungenRichtig einblenden
		public void einblendenRueckmeldungenRichtig() {
			this.rueckmeldungenRichtig.setVisible(true);
		}
		
		//rueckmeldungenRichtig ausblenden 
		public void ausblendenRueckmeldungenRichtig() {
			this.rueckmeldungenRichtig.setVisible(false);
		}
		
		//rueckmeldungenFalsch sichtbar machen
		public void zeigenRueckmeldungenFalsch() {
			this.rueckmeldungenFalsch.setVisible(true);
		}
			
		//rueckmeldungenFalsch ausblenden 
		public void ausblendenRueckmeldungenFalsch() {
			this.rueckmeldungenFalsch.setVisible(false);
		}	
	
		
		
	
		
	
		
		//starten den Versuch mit Versuchsaufklärung
		public void weiter(){
			this.window.cardLayout.show(this.window.cards, "CorsiAufgabe");
		}
		
		
		
		//setzt das flag eingabeBeendet auf false zurück
		public void eingabeBeendetFalseSetzen(){
			this.eingabeBeendet = false;
		}
		
		//gibt den Wert der booleanen Variablen 
		public boolean statusEingabeBeendet(){
			return this.eingabeBeendet;
		}
		
		//gibt Status "naechsteSequenzAngefordert"
		public boolean statusNaechsteSequenzAngefordert() {
			return naechsteSequenzAngefordert;
		}
		
		//Mogler-Meldung einblenden
		public void moglerMeldung() {
		this.moglerMeldung.setVisible(true);
		this.corsiBloecke.setVisible(false);
		this.buttonNaechsteSequenzStarten.setVisible(false);
		this.buttonEingabeBeenden.setVisible(false);
		this.ausblendenRueckmeldungenFalsch();
		
		}
}
 
C

Camino

Gast
Jetzt fügst du in Card3 ja auch 4 Komponenten in den CENTER-Bereich ein:
this.add(rueckmeldungenRichtig, BorderLayout.CENTER);
this.add(rueckmeldungenFalsch, BorderLayout.CENTER);
this.add(corsiBloecke, BorderLayout.CENTER);
this.add(moglerMeldung, BorderLayout.CENTER);

Und die letzte davon setzt du auch noch auf setVisible(false). Brauchste dich ja nicht wundern, wenn nichts angezeigt wird. Also, erst nochmal überlegen, was da denn nun angezeigt werden soll. Dann NUR das in den CENTER-Bereich rein.
 

Rufus.Mueller

Bekanntes Mitglied
Okay, damit hätte ich nicht gerechnet. Bisher habe ich ja meist mit Null-Layout gearbeitet. Da konnte ich problemlos mehrere Labels übereinander legen, und immer das gerade benötigte auf visible(true) setzen. Bei nicht-durchsichtigen Komponenten war es schlimmstenfalls so, das man nur die zuletzt hinzugefügte zu sehen bekam, weil die anderen unten drunter lagen. Bei Layout ist das ja völlig anders, ich hätte nicht gedacht, dass in einem solchen Fall noch nicht einmal die zuletzt hinzugefügte Komponente angezeigt wird. Man muss die Verschachtelung also sehr weit treiben. Damit hast Du mir gleich bei zwei Problemen geholfen, die für mich absolut unlösbar gewesen wären. Herzlichen Dank dafür!
 
C

Camino

Gast
Okay, damit hätte ich nicht gerechnet. Bisher habe ich ja meist mit Null-Layout gearbeitet. Da konnte ich problemlos mehrere Labels übereinander legen, und immer das gerade benötigte auf visible(true) setzen.
Du könntest auch nur 1 Label in dein Layout einfügen und da dann den Text ändern, je nachdem was du dort anzeigen möchtest.

Man muss die Verschachtelung also sehr weit treiben.
Nö, eigentlich sollte man es nicht zu weit treiben, sondern nur so weit, wie notwendig. Also vorher überlegen, was man in seiner Anwendung anzeigen möchte und sich dann das oder die LayoutManager raussuchen und ggf. verschachteln.
Ich kann also für meinen Frame ein BorderLayout nehmen, und z.B. in den CENTER-Bereich ein umfangreiches Formular einfügen, welches ein JPanel ist und wiederum mit einem GridBagLayout seine Komponenten anordnet.
Es sind ja nicht so viele verschiedene LayoutManager, so dass man sich deren Funktionsweise anschauen und je nach Bedarf auswählen kann. Jeder LayoutManager hat halt seine Besonderheiten und spezielle Anordnungen der Komponenten, die man kennen sollte, um erfolgreiche Ergebnisse zu erhalten.
 
Zuletzt bearbeitet von einem Moderator:

Ähnliche Java Themen

Neue Themen


Oben