Java GUI

Hallo Zusammen,

ich habe in java ein kleines spiel geschrieben, bei dem man "raumschiffe" (einfach kästchen im JPanel ;-) ) abschiessen muss.

nun wollte ich ein Textfeld anlegen, das den Punktestand anzeigt.
habe dazu JLabel gewählt.
das funktioniert.
aber leider kann ich es nicht aktualisieren. d. h. es bleiben immer 0 punkte drin.
die punkte werden richtig mitgezählt in einer eigenen klasse... habs getestet.

übrigens erfolgt der normale refresh über diese methode für die grafischen sachen:
paintComponent(Graphics g)

ich kopiere jetzt mal noch den code rein, für die main klasse, und die klasse mit der paintComponent, die ich ZeichenPanal genannt habe.
außerdem gibt es noch die klassen Geschuetz, Raumschiff, Projektil, punkte und mehrThread.
hauptsächlich werden in den klassen die koordinaten mitgerechnet wenn sich ein objekt bewegen soll. und von dort aus dann abgerufen vom panel fürs zeichnen.

tscheckt das wer?
(ich glaub ich würds jetzt net verstehen... ;-) )

naja... eigentlich gehts ja nur darum wie ich den text vom JLabel im JPanel refreshen kann...

danke schon mal und gruß,
Peter.

Code:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
 


public class Spaceinvaders implements KeyListener
{
	Geschuetz Gun;
	static JFrame frame;
	Raumschiff Alien;
	Projektil Schuss;
	punkte pustand;
		
	public static void main(String[] args) 
	{
		//Ein Objekt Aufrufer wird angelegt:
		Spaceinvaders gui = new Spaceinvaders();
		
		gui.los();
	}

	
	public void los() 
	{		
		//Frame und Panel werden angelegt:
		frame = new JFrame();
		ZeichenPanel zeichnen = new ZeichenPanel();
		JLabel textfeld = new JLabel("  Space-Invaders Revival. Developed by Peter Singer. Version Beta 2.0                                                                                                        Punkte: "+punkte.getStaticPunkte());   
		
		frame.addKeyListener(this);
		
		//Anlegen der Steuerungsobjekte:
		
		double ra = Math.random();
		double rb = ra * 10;
		int rc = (int)rb;
		int rd = rc * rc * rc;
		
		Gun = new Geschuetz(390,525,20,50);
		Alien = new Raumschiff (rd,0,80,80);
		Schuss = new Projektil(0,0,0,0);
	
		//Hier noch die Daten für den Frame:
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(800,600);
		frame.setVisible(true);	
	
		Spaceinvaders.frame.getContentPane().add(BorderLayout.SOUTH, textfeld);
		frame.getContentPane().add(BorderLayout.CENTER, zeichnen);
	}
	
	public void keyPressed(KeyEvent event)
	{
		int key = event.getKeyCode();
		
		//Links
		if (key == 37)
		{
			int a = Geschuetz.getXkoordinate();
			int b = Geschuetz.getYkoordinate();
			if (a > 0)
			{
				a=a-20;
				Gun.setKoordinaten(a, b);
			}
		}
		
		//Rechts
		if (key == 39)
		{
			int a = Geschuetz.getXkoordinate();
			int b = Geschuetz.getYkoordinate();
			if (a < 780)
			{
				a=a+20;
				Gun.setKoordinaten(a, b);
			}
		}
		
		//Feuer
		if (key == 32)
		{
			int a = Geschuetz.getXkoordinate();
			int b = Geschuetz.getYkoordinate();
			b = b - 20;
			
			Schuss.setKoordinaten(a, b);
			Schuss.setGroesse(20, 20);
		}
		frame.repaint();
		if (key == 32)
		{
			Feuer();
		}
	}

	public void keyReleased(KeyEvent event)
	{
		
	}
	public void keyTyped(KeyEvent event)
	{
		
	}
	
	public void Feuer  ()
	{
		Runnable threadJob = new MehrThread();
		Thread r = new Thread(threadJob);
		r.start ();
	}
	
	public static void Grakfikaufruf ()
	{
		frame.repaint();
	}
}








import java.awt.*;
import javax.swing.*;

public class ZeichenPanel extends JPanel
{
	public void paintComponent(Graphics g)
	{
		int gxk = Geschuetz.getXkoordinate();
		int gyk = Geschuetz.getYkoordinate();
		int ggb = Geschuetz.getBreite();
		int ggh = Geschuetz.getHoehe();
		
		int hr=Raumschiff.getYkoordinate ();
		Raumschiff.setStaticYKoordinate(hr+1);	
		
		int rxk = Raumschiff.getXkoordinate();
		int ryk = Raumschiff.getYkoordinate();
		int rgb = Raumschiff.getBreite();
		int rgh = Raumschiff.getHoehe();
		
		int pxk = Projektil.getXkoordinate();
		int pyk = Projektil.getYkoordinate();
		int pgb = Projektil.getBreite();
		int pgh = Projektil.getHoehe();		

		//Alles was hier drin steht, wird nicht vom
		//aufrufer direkt gestartet. 
		//Alles was hier drin steht, wird grafisch
		//ausgeführt:
			
		//altes, bildloses geschütz:
		//g.setColor(Color.blue);
		//g.fillRect(gxk,gyk,ggb,ggh);
		
		g.setColor(Color.black);
		g.fillRect(rxk,ryk,rgb,rgh);
		
		g.setColor(Color.yellow);
		g.fillRect(pxk,pyk,pgb,pgh);
		
		Image image = new ImageIcon("geschuetz2.jpg").getImage();
		g.drawImage(image,gxk-4,gyk-40,this);
		
	}
}
[CODE]
 
Ich nehme an, deine Frage bezieht sich auf diese Zeile:

JLabel textfeld = new JLabel(" Space-Invaders Revival. Developed by Peter Singer. Version Beta 2.0 Punkte: "+punkte.getStaticPunkte());

Hier gibt es zwei Sachen zu beachten:
1. Textfeld ist hier eine lokale Variable.
Das heißt, du kommst später zur Laufzeit nicht mehr (gut) an das Feld dran und kannst die Punkte nicht überschreiben
2. Du weist dem Label nur einmal einen Text zu und änderst diesen später nicht mehr. durch das ändern des Punktstands hinterher wird natürlich der Wert nicht aktualisiert.
Vergleiche:
int i = 4;
String t = "Test " + i;
i = 5; // In t steht immer noch "Test 4", da die Zeile drüber eine Wertüberweisung und keine Objektüberweisung ist.

Hier ein kleiner Beispielcode, wie man es besser machen könnte:

Code:
class Test {

private int punkte;
private JLabel label;

public void Test()
punkte = 0;
label = new JLabel("Punkte " + punkte);
}

public void run() {
...
punkte = punkte + 500;
updatePunkte();
...
}

private void updatePunkte() {
label.setText("Punkte " + punkte);
}

}
So kannst du eine private Instanz, die Klassenweit bekannt ist, gut aktualisieren, wogegen eine Instanz, die nur in der Funktion sichtbar ist, nur schwer (z.B. über Event-Handler) zu manipulieren ist.

Ich hoffe, es ist jetzt etwas klarer.
Du könntest z.B. im Openbook zu "Java ist auch eine Insel" noch etwas nachlesen, speziell im Kapitel über Events.

mfg, metax.
 
hmmm... das mit der setText methode hatte ich schon mal getestet.
hab sie jetzt nochmal so in meine punkte-klasse reingeschrieben.
muss allerdings dazusagen dass ich sie static gemacht habe.
jedenfalls kommt folgende fehlermeldung:

----------------------------------------------------------------
Exception in thread "Thread-3" java.lang.NullPointerException
at punkte.setStaticPunkte(punkte.java:15)
at MehrThread.los(MehrThread.java:46)
at MehrThread.run(MehrThread.java:9)
at java.lang.Thread.run(Unknown Source)
----------------------------------------------------------------

wenn ich es ohne static mache, und dann in der hauptklasse (Spaceinvaders), so kommt folgende fehlermeldung:

----------------------------------------------------------------
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Spaceinvaders.keyPressed(Spaceinvaders.java:98)
at java.awt.Component.processKeyEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Window.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
----------------------------------------------------------------



=============================
nachtrag: komisch... wenn ich

int zz = punkte.getStaticPunkte();
textfeld.setText(" Punkte: "+zz);

direkt in der main kurz nach dem anlegen des textfeldes mache, wird der alte eintrag überschieben. da funktioniert es also.
aber wenn ich es unten in einer Listener Funktion reingebe, kommen wieder die fehlermeldungen.
aber wenn ich es oben drin lassen würde, würde es ja nicht mehr aufgerufen, und könnte nicht verändert werden...
 
Ich würde gerne mal den kompletten Quelltext sehen.
An den paar Schnipseln kann man nicht wirklich erkennen, wo das Problem liegt
(zumal du eine etwas unkonventionelle Interpretation des Event-Modells hast ...)
Du kannst die relevanten Javadateien ja auch als zip oder jar irgendwo hochladen...

mfg, metax.

P.S: Nullpointerexception bekommst du immer dann, wenn du versuchst, auf ein Objekt zuzugreifen, welches null (also kein Objekt) ist. Meistens nicht initialisierte Objektvariablen.

z.B.:
// Falsch
Label l1;
l1.setText("Hallo") // NullPointerException!
// Richtig
Label l2;
l2 = new Label();
l2.setText("Hallo");

Mit geeigneten Debuggern (z.B. in Eclipse) kannst du auch genau sehen, welchen Zustand deine Variablen zu diesem Zeitpunkt haben und wodurch der Fehler genau verursacht wird (steht auch im Stacktrace).
 
Schau dir mal SpaceInveraders.java Zeile 32 an:
JLabel textfeld = new JLabel(...);

Du hast zwar eine klassenweite Variable "textfeld",aber wenn du in Zeile 32 den Objekttyp mit angibst, referenzierst du statt dessen auf eine lokale Variable mit dem selben Namen, welche die globale Variable überdeckt. Natürlich bleibt die globale Variable nach wie vor null, da du nur in die lokale Variable was reinschreibst und du bekommst eine NullpointerException beim Zugriff auf die globale Variable.
Lass einfach den Typ in Zeile 32 weg, dann kannst du die Zuweisung mit setText() hoffentlich ohne Probleme implementieren:
textfeld = new JLabel(...);

mfg, metax.
 
es funktioniert :-)
vielen Dank!!!!
ist ja echt krass was so ein kleiner fehler alles auslösen kann ;-)

schönen gruß,
Peter.
 
Zurück
Oben