Hallo,
bin wieder dabei mich mit GUIs zu beschäftigen.
Zur Übung wollte ich einfach mal ein kleines Memory basteln.
Dabei bin ich folgendes Problem gestoßen:
Zunächst mal meine Klassen
Das Hauptfenster
Das Panel mit den Schaltflächen(im Moment noch mit Text)
Der ActionListener für die Schaltflächen
leicht modifizierter JButton (für die Gewinnbedingung)
Sorry für den vielen Quelltext, aber ich denke so kann ich mein Problem am besten erklären.
Wenn das initiiert wird (initiateSpielfeld) wird für Buttons der ActionListener registriert, der die Funktionalität regelt.
Dann wird im SpielFenster ein ActionListener registriert, der kontrolliert ob die Gewinnbedingung erfüllt ist.
Das Problem ist nun die Reihenfolge, in der diese vermutlich abgearbeitet werden.
Da der in SpielFenster registrierte ActionListener scheinbar zuerst ausgeführt wird, ist die win() nie wahr. Da ja dann erst später im anderen ActionListener die Buttons auf consumed=true gesetzt werden.
Nach meinen Versuche scheint es mir, als ob der zuletzt registrierte Listener zuerst ausgeführt wird.
Stimmt das?
Falls ja würde ich das Problem in den Griff bekomme, indem ich das Label nicht zum SpielFenster hinzufüge, sondern zum Spielfeld.
Allerdings möchte ich das eigentlich ungern, da das Spielfeld eigentlich auch wirklich nur die Schaltflächen enthalten soll.
Welche anderen möglichkeiten habe ich? (am besten ohne das Klassenmodell groß zu ändern)
Vielen Dank im Vorraus
bin wieder dabei mich mit GUIs zu beschäftigen.
Zur Übung wollte ich einfach mal ein kleines Memory basteln.
Dabei bin ich folgendes Problem gestoßen:
Zunächst mal meine Klassen
Das Hauptfenster
Java:
package main;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class SpielFenster extends JFrame {
Spielfeld spielfeld;
JLabel spielstandanzeige;
public SpielFenster() {
super.setTitle("Memory");
super.setBounds(0, 0, 750, 750);
super.setVisible(true);
super.setLayout(new BorderLayout());
this.spielfeld = new Spielfeld();
super.add(spielfeld, BorderLayout.NORTH);
this.spielstandanzeige = new JLabel("Spiel läuft");
this.spielstandanzeige.setSize(100, 100);
super.add(spielstandanzeige, BorderLayout.SOUTH);
for (SpielFeldJButton btn : this.spielfeld.buttons.keySet()) {
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if (win()) {
spielstandanzeige.setText("Gewonnen");
System.out.println("gewonnen");
}
}
});
}
super.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public boolean win() {
for (SpielFeldJButton btn : this.spielfeld.buttons.keySet()) {
if (!btn.isConsumed()) {
return false;
}
}
return true;
}
}
Das Panel mit den Schaltflächen(im Moment noch mit Text)
Java:
package main;
public class Spielfeld extends JPanel {
HashMap<SpielFeldJButton, String> buttons;
public Spielfeld() {
this.buttons = new HashMap<SpielFeldJButton, String>();
this.initiateSpielfeld(new SpielfeldActionListener(this));
}
private void initiateSpielfeld(ActionListener al) {
super.setSize(500, 500);
super.setBackground(Color.CYAN);
super.setLayout(new GridLayout(2, 2));
super.setVisible(true);
this.buttons.put(new SpielFeldJButton("Eins"), "Fisch");
this.buttons.put(new SpielFeldJButton("Zwei"), "Fisch");
this.buttons.put(new SpielFeldJButton("Drei"), "Affe");
this.buttons.put(new SpielFeldJButton("Vier"), "Affe");
for (SpielFeldJButton btn : buttons.keySet()) {
btn.setVisible(true);
btn.setSize(200, 200);
btn.setBackground(Color.BLUE);
btn.setForeground(Color.WHITE);
btn.addActionListener(al);
super.add(btn);
}
}
}
Der ActionListener für die Schaltflächen
Java:
package main;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
public class SpielfeldActionListener implements ActionListener {
private Spielfeld spielfeld;
private int counter;
private SpielFeldJButton firstclicked;
private SpielFeldJButton secondclicked;
public SpielfeldActionListener(Spielfeld spielfeld) {
this.spielfeld = spielfeld;
counter = 0;
}
@Override
public void actionPerformed(ActionEvent e) {
if (counter == 0) {
this.setFirstclicked((SpielFeldJButton) e.getSource());
this.getFirstclicked().setEnabled(false);
this.getFirstclicked().setText(
spielfeld.buttons.get(this.getFirstclicked()));
counter++;
} else if (counter == 1) {
this.setSecondclicked((SpielFeldJButton) e.getSource());
this.getSecondclicked().setEnabled(false);
this.getSecondclicked().setText(
spielfeld.buttons.get(this.getSecondclicked()));
counter--;
try {
Thread.sleep(500);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
if (spielfeld.buttons.get(this.firstclicked).equals(
spielfeld.buttons.get(this.secondclicked))
&& counter != 1) {
this.getFirstclicked().setText("Päärchen gefunden");
this.getSecondclicked().setText("Päärchen gefunden");
this.firstclicked.setConsumed(true);
this.secondclicked.setConsumed(true);
} else if (!spielfeld.buttons.get(this.firstclicked).equals(
spielfeld.buttons.get(this.secondclicked))
&& counter != 1) {
this.getFirstclicked().setText("schonmal geklickt");
this.getSecondclicked().setText("auch schonmal geklickt");
this.getFirstclicked().setEnabled(true);
this.getSecondclicked().setEnabled(true);
}
}
public JButton getFirstclicked() {
return firstclicked;
}
public void setFirstclicked(SpielFeldJButton firstclicked) {
this.firstclicked = firstclicked;
}
public JButton getSecondclicked() {
return secondclicked;
}
public void setSecondclicked(SpielFeldJButton secondclicked) {
this.secondclicked = secondclicked;
}
public boolean win() {
for (SpielFeldJButton btn : this.spielfeld.buttons.keySet()) {
if (!btn.isConsumed()) {
return false;
}
}
return true;
}
}
leicht modifizierter JButton (für die Gewinnbedingung)
Java:
public class SpielFeldJButton extends JButton {
private boolean consumed;
public SpielFeldJButton(String text){
super(text);
this.consumed=false;
}
public boolean isConsumed() {
return consumed;
}
public void setConsumed(boolean consumed) {
this.consumed = consumed;
}
}
Sorry für den vielen Quelltext, aber ich denke so kann ich mein Problem am besten erklären.
Wenn das initiiert wird (initiateSpielfeld) wird für Buttons der ActionListener registriert, der die Funktionalität regelt.
Dann wird im SpielFenster ein ActionListener registriert, der kontrolliert ob die Gewinnbedingung erfüllt ist.
Das Problem ist nun die Reihenfolge, in der diese vermutlich abgearbeitet werden.
Da der in SpielFenster registrierte ActionListener scheinbar zuerst ausgeführt wird, ist die win() nie wahr. Da ja dann erst später im anderen ActionListener die Buttons auf consumed=true gesetzt werden.
Nach meinen Versuche scheint es mir, als ob der zuletzt registrierte Listener zuerst ausgeführt wird.
Stimmt das?
Falls ja würde ich das Problem in den Griff bekomme, indem ich das Label nicht zum SpielFenster hinzufüge, sondern zum Spielfeld.
Allerdings möchte ich das eigentlich ungern, da das Spielfeld eigentlich auch wirklich nur die Schaltflächen enthalten soll.
Welche anderen möglichkeiten habe ich? (am besten ohne das Klassenmodell groß zu ändern)
Vielen Dank im Vorraus