Java MouseEvent Problem

02/24/2012 16:37 Belur#1
Hey E*pvpers.

Ich darf zur Zeit fürn Info Lk das Game of Life in Greenfoot umsetzen.
Manch einer mags kennen. Ist ja einer der populärsten Automaten die es gibt.


Jedenfalls wollte ich es noch so einrichten, dass ich auf eine Zelle auf dem Bildschirm klicke und diese dann gefüllt wird. Als der Status im 2-d Array auf true gesetzt wird und schwarz gefärbt wird. Die beiden Dinge an sich krieg ich auch hin bzw hab ich schon das Vorgehen dafür.

Dieses Feld sieht erstmal so aus:

[Only registered and activated users can see links. Click Here To Register...]

Ich hab versucht die x und y Werte und über getX() und getY() zu bekommen.

Problem ist leider, dass der Wert (0/0) über die Methoden getX() und getY() nicht am Anfang des "Spielfeldes". Der nimmt die halt von Anfang des Greenfoot Fensters, wies ja auch normal ist. Wenn ich außerhalb des Feldes klicke ist die logische Folge irgendein OutOfBounds Fehler. Ist mir auch klar.

Ich möchte ja im Prinzip auf eine Zelle im Feld klicken und von dieser Stelle den x und y Wert des Arrays zzrückkriegen. Jede Zelle steht für einen Eintrag vom Array nur zum Verständnis.

Hoffe jemand versteht das Problem.


~Greets

Belur
02/24/2012 17:02 Dr. Coxxy#2
Code:
int tempx = GetX();
int tempy = GetY();
int clickedX = -1;
int clickedY = -1;

tempx -= Feld.x;
tempy -= Feld.y;

if (tempx > 0 && tempx < Feld.w && tempy > 0 && tempy < Feld.h) // Es wurde ins spielfenster geklickt
{
	clickedX = tempx/10; //coords noch durch feldgröße teilen... (10 px soweit ich mich vom letzten thread erinner...)
	clickedY = tempy/10;
}

if (clickedX >= 0 && clickedY >= 0)
{
	Array[clickedX][clickedY].clicked = true; // oder was auch immer du hier machen willst...
}
Feld.x und Feld.y sind die entfernungen des spielfeldes in pixeln vom oberen linken rand.
Feld.w und Feld.h sind breite und höhe des feldes in pixeln.

solltest du noch in ne funktion packen das ganze, z.b. bool ScreenToOffset(int x, int y, int returnx, int returny) oder ähnliches...

EDIT:
hups, kleiner fehler :P

EDIT2:
grad nochmal durchgelesen und dich glaube ich missverstanden...

brauchst folgende dinge (kann dir leider keinen genauen code geben, da ich in java nix mache) (alles in pixeln):

Mauskoordinaten bei klick.
wenn diese nicht schon relativ zum fenster sind, also die differenz zur linken oberen ecke des fensters sind, auch noch die x und y position des fensters.
die x und y koordinaten von der oberen linken ecke des zeichenabschnitts (also deines spielfeldes).
die breite und höhe deines spielfelds.
die breite und höhe eines spielfeldabschnittes.

dann kannst dus mit der oben beschriebenen methode machen.
02/24/2012 19:08 xNopex#3
Code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JApplet;

public class TestClass extends JApplet implements MouseListener {

	private final int SIZE = 10; // Seitenlänger einer Zelle
	private final int GAP = 2; // Lücke zwischen zwei Zellen
	private int areaX = 20; // X-Koordinate des linken oberen Eckpunktes des
							// Feldes
	private int areaY = 40; // Y-Koordinate des linken oberen Eckpunktes des
							// Feldes
	private boolean area[][]; // die einzelnen Zellen

	public void init() {
		addMouseListener(this);
		// Erstelle Feld Dimension 10*10 Zellen
		this.area = new boolean[10][10];
		for (int i = 0; i < 10; i++) {
			for (int j = 0; j < 10; j++) {
				this.area[i][j] = false;
			}
		}
	}

	@Override
	public void mouseClicked(MouseEvent arg0) {
		// Mausklick verarbeiten
		int x = arg0.getX();
		int y = arg0.getY();

		// Lege Bereich der Zellen fest
		int xMin = this.areaX;
		int xMax = this.areaX + this.area[0].length * this.SIZE
				+ (this.area[0].length * this.GAP - 1);
		int yMin = this.areaY;
		int yMax = this.areaY + this.area.length * this.SIZE
				+ (this.area.length * this.GAP - 1);

		// Nur Mausklicks innerhalb des Bereiches der Zellen sollen verarbeitet
		// werden
		if (x > xMin && x < xMax && y > yMin && y < yMax) {
			// Abstand der X/Y - Koordinate zum oberen linken Eckpunkt
			int actualX = x - xMin;
			int actualY = y - yMin;

			// Abstand als Index fürs Array umrechnen
			int atX = (int) (Math.round(actualX / (this.SIZE + this.GAP)));
			int atY = (int) (Math.round(actualY / (this.SIZE + this.GAP)));

			// Zelle ändern und neuzeichnen lassen
			this.area[atY][atX] = !this.area[atY][atX];
			this.repaint();
		}
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mousePressed(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	public void paint(Graphics g) {
		// Feld zeichnen lassen
		for (int i = 0; i < 10; i++) {
			for (int j = 0; j < 10; j++) {
				if (this.area[i][j]) {
					g.setColor(Color.green);
				} else {
					g.setColor(Color.black);
				}
				g.fillRect(this.areaX + j * (this.SIZE + this.GAP), this.areaY
						+ i * (this.SIZE + this.GAP), this.SIZE, this.SIZE);
			}
		}
	}

}
Hab das mal schnell geschrieben.. Hat soweit bei mir funktioniert. Evtl. hilfts dir weiter. Hab mir auch extra viel Mühe bei den Kommentaren gegebn (not).
02/25/2012 11:52 Belur#4
Hatte nochmal mit meinen Lehrer gesprochen und der sagte mir ich sollte es ruhig anders machen als mit der Maus. Trotzdem werd ich das auch noch hinzufügen ;)


Also: Ich hab eine Unterklasse von Actor.

Wenn ich hiervon ein Object erstelle und auf das Spielfeld setze, komme ich ja über getX() und getY() and die Werte dieses Objects. Und die x und y-werte davon sind ja dieselben wie auf der jeweiligen Zelle worauf das Object ist. (Kann man in Greenfoot ja beliebig hin und herziehen).

Hatte mir dazu folgenden Quellcode gedacht:


PHP Code:
public class Zelleneditor extends Actor
{
    
/**
     * Act - do whatever the Zelleneditor wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    
Spielfeld sp = new Spielfeld();
    public 
Zelleneditor(){

    }

    public 
void act() 
    {
        
int x getX();
        
int y getY();

        if(
sp.cells[x][y] == false){

            
sp.cells[x][y] = true;
            
sp.bg.drawImage(sp.lebendx*10y*10);

        }else{
            
sp.cells[x][y] = false;
            
sp.bg.drawImage(sp.totx*10y*10);

        }
    }    


Ich führe also act bei dem Objekt aus, lass mir die x und y Werte geben und füg auf der Position eine Zelle ein bzw lösche eine lebende.
Hoffe das ist verständlich.

Einziges Problem:

Syntax scheint ok zu sein, doch ich krieg nach dem Übersetzen ne Fehlermeldung von wegen Java.out.of.Memory Java heap space.


Kann da persönlich wenig mit anfangen und weiß nicht worans liegt.


Vllt wisst ihr da wieder weiter O.o


Danke


Belur


#edit:

Okay die Fehlermeldung hab ich wegbekommen. Dafür passiert einfach garnichts wenn ich die act methode von dem neuen Object aufrufe. Hab schon sp.repaint() geaddet trotzdem nichts O.o