getSize() - Echte Höhe bestimmen

Ja ist richtig, da fehlt noch nen final vor dem int i.

Dafür gibt es doch die API, da steht das alles wunderbar beschrieben :wink:
Die Variante von bERt0r hilft dir noch nicht dabei rauszufinden welcher Tisch oder Stuhl angeklickt wurde. Ich würde die Variante mit der anonymen Klasse bevorzugen.

Okay okay, dann probiere ich das mal so mit anonymer Klasse.

			spielfeldlabeltisch.get(a).setBackground(Color.ORANGE);
			spielfeldlabeltisch.get(a).addMouseListener(new MouseAdapter() {
			    @Override
			    public void mouseClicked(MouseEvent e) {
			      System.out.println("Tisch "+a+" wurde gedrückt!");
			    }
			});
		}```

Ein final a in dieser Situation erschließt sich mir und Eclipse aber irgendwie nicht. In einer for-Schleife die Hochzählt, kann das doch nicht gutgehen?
Oder meinst Du an einer anderen Stelle, mache ich was falsch?

getSource liefert dir das JLabel auf das geklickt wurde. Du kannst einfach schreiben JLabel label = (JLabel)event.getSource();
Aber ja, wenn dich eh nur die Nummer des Labels interessiert ists mit der anonymen Klasse wohl einfacher.

Ich habs nun so gemacht:

private int tischnummer;
for(JLabel a:spielfeldlabeltisch) {
            a.setBackground(Color.ORANGE);
            final int tischindex = spielfeldlabeltisch.indexOf(a);
            a.addMouseListener(new MouseAdapter() {
            	@Override
            	public void mouseClicked(MouseEvent e) {
            		stuhlnummer = tischindex;
            	}
            });
        }
        for(JLabel b:spielfeldlabelstuhl) {
            b.setBackground(Color.RED);
            final int stuhlindex = spielfeldlabelstuhl.indexOf(b);
            b.addMouseListener(new MouseAdapter() {
            	@Override
            	public void mouseClicked(MouseEvent e) {
            		tischnummer = stuhlindex;
            	}
            });
        }```

Ein wenig primitiv, manche werden sicherlich sagen, sehr umständlich, aber es funktioniert.
Ich lege über einen final Integer und indexOf die Nummer fest, innerhalb der Methode.
Und für außerhalb, um den Wert des aktuellst angeklickten Tisch zu nutzen, speichere ich das dann direkt um in stuhlnummer und tischnummer.

Sieht noch jemand Bedarf das einfacher zu schreiben?

Ansonsten funktioniert das so, danke! :) 


Gruß
Lukas

Wenn Du ohnehin den Index der Objekte in der Liste benötigst nutzte doch bitte eine “normale” for Schleife, statt eine for each zu verwenden und darin jedesmal den Index zu erfragen.

Hallöle,

ich habe nach den ganzen bisherigen Fortschritten nochmal richtig Krawall mit Bildern… Wieso muss das in Java so unnötig kompliziert sein?

Also, meine Klasse Spielfeld sieht so aus:


import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.JLabel;
import javax.swing.JPanel;

class Spielfeld extends JPanel {

	protected static JLabel spielfeldlabel[][] = new JLabel[11][11];
	protected static ArrayList<JLabel> spielfeldlabeltisch = new ArrayList<JLabel>(12);
	protected static ArrayList<JLabel> spielfeldlabelstuhl = new ArrayList<JLabel>(24);
	protected static int stuhlnummer;
	protected static int tischnummer;
	
	public Spielfeld() {
		setLayout(new GridLayout(11,11));
		for(int i=0;i<11;i++) {
			for(int n=0;n<11;n++) {
				spielfeldlabel[n]** = new JLabel(n+","+i);
				spielfeldlabel[n]**.setBackground(new Color(255,255,255));
				spielfeldlabel[n]**.setOpaque(true);
				add(spielfeldlabel[n]**);
			}
		}
		feldmalen();
	}
	
	public void feldmalen() {
		spielfeldlabeltisch.add(spielfeldlabel[4][3]);
		spielfeldlabeltisch.add(spielfeldlabel[5][2]);
		spielfeldlabeltisch.add(spielfeldlabel[6][3]);
		spielfeldlabeltisch.add(spielfeldlabel[7][4]);
		spielfeldlabeltisch.add(spielfeldlabel[8][5]);
		spielfeldlabeltisch.add(spielfeldlabel[7][6]);
		spielfeldlabeltisch.add(spielfeldlabel[6][7]);
		spielfeldlabeltisch.add(spielfeldlabel[5][8]);
		spielfeldlabeltisch.add(spielfeldlabel[4][7]);
		spielfeldlabeltisch.add(spielfeldlabel[3][6]);
		spielfeldlabeltisch.add(spielfeldlabel[2][5]);
		spielfeldlabeltisch.add(spielfeldlabel[3][4]);
		
		spielfeldlabelstuhl.add(spielfeldlabel[4][4]);
		spielfeldlabelstuhl.add(spielfeldlabel[5][1]);
		spielfeldlabelstuhl.add(spielfeldlabel[6][2]);
		spielfeldlabelstuhl.add(spielfeldlabel[7][3]);
		spielfeldlabelstuhl.add(spielfeldlabel[8][4]);
		spielfeldlabelstuhl.add(spielfeldlabel[7][5]);
		spielfeldlabelstuhl.add(spielfeldlabel[6][6]);
		spielfeldlabelstuhl.add(spielfeldlabel[5][7]);
		spielfeldlabelstuhl.add(spielfeldlabel[4][6]);
		spielfeldlabelstuhl.add(spielfeldlabel[3][5]);
		spielfeldlabelstuhl.add(spielfeldlabel[2][4]);
		spielfeldlabelstuhl.add(spielfeldlabel[3][3]);
		spielfeldlabelstuhl.add(spielfeldlabel[4][2]);
		spielfeldlabelstuhl.add(spielfeldlabel[5][3]);
		spielfeldlabelstuhl.add(spielfeldlabel[6][4]);
		spielfeldlabelstuhl.add(spielfeldlabel[9][5]);
		spielfeldlabelstuhl.add(spielfeldlabel[8][6]);
		spielfeldlabelstuhl.add(spielfeldlabel[7][7]);
		spielfeldlabelstuhl.add(spielfeldlabel[6][8]);
		spielfeldlabelstuhl.add(spielfeldlabel[5][9]);
		spielfeldlabelstuhl.add(spielfeldlabel[4][8]);
		spielfeldlabelstuhl.add(spielfeldlabel[3][7]);
		spielfeldlabelstuhl.add(spielfeldlabel[2][6]);
		spielfeldlabelstuhl.add(spielfeldlabel[1][5]);
		
		
		for(JLabel a:spielfeldlabeltisch) {
            a.setBackground(Color.ORANGE);
            final int tischindex = spielfeldlabeltisch.indexOf(a);
            a.addMouseListener(new MouseAdapter() {
            	@Override
            	public void mouseClicked(MouseEvent e) {
            		System.out.println("Tisch: "+tischindex);
            		stuhlnummer = tischindex;
            	}
            });
        }
        for(JLabel b:spielfeldlabelstuhl) {
            b.setBackground(Color.RED);
            final int stuhlindex = spielfeldlabelstuhl.indexOf(b);
            b.addMouseListener(new MouseAdapter() {
            	@Override
            	public void mouseClicked(MouseEvent e) {
            		System.out.println("Stuhl: "+stuhlindex);
            		tischnummer = stuhlindex;
            	}
            });
        }
   
	}
	
}

class Kartenstapel extends JPanel {
	public Kartenstapel() {
		setLayout(new GridLayout(5,2));
		Random rand = new Random();
		for(int i=0;i<10;i++) {
			JLabel label = new JLabel();
		    label.setBackground(new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255)));
		    label.setOpaque(true);
		    add(label);
		}
	}
}
 
class AufbauHilfe {
    public static GridBagConstraints createGridBagConstraints(int x, int y, int width, int height, int weightX, int weightY) {
        GridBagConstraints constraints = new GridBagConstraints();
        constraints.fill = GridBagConstraints.BOTH;
        constraints.gridx = x;
        constraints.gridy = y;
        constraints.gridwidth = width;
        constraints.gridheight = height;
        constraints.weightx = weightX;
        constraints.weighty = weightY;
 
        return constraints;
    }
 
    public static JLabel createRandomBackgroundLabel(String text) {
        Random rand = new Random();
        JLabel label = new JLabel(text);
        label.setBackground(new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255)));
        label.setOpaque(true);
 
        return label;
    }
}```

Diese 12 Tische und 24 Stühle bekommen nun alle jeweils ein Bild.

Ich möchte das anhand eines Beispielbildes klar machen.
Mein Ordnerverzeichnis sieht so aus:
- bin
- src
- resources
Das Bild liegt im resources Ordner und heißt `demo_DE.jpg`.

Nun möchte ich gerne in einer externen Klasse die Bilder dazu festlegen:
In der Klasse Spielstart:
```public static void spielfeldgenerieren() {
		for(int n=0;n<12;n++) {
			tische.add(new Tisch());
			tische.get(n).setLand(laenderkarten.get(0));
			Icon icon = new ImageIcon("/././resources/demo_CF.jpg");
			Spielfeld.spielfeldlabeltisch.get(n).setIcon(icon);
			laenderkarten.remove(0);
		}
		for(int n=0;n<24;n++) {
			stuehle.add(new Stuhl());
		}```

Hier geht er die 12 Tische einmal durch (new Tisch sind einfache Tischklassen, die hier nicht weiter relevant ist und gibt dem einen Namen).

Nun möchte ich mit diesen zwei Zeilen das Foto festlegen:
```Icon icon = new ImageIcon("/././resources/demo_CF.jpg");
			Spielfeld.spielfeldlabeltisch.get(n).setIcon(icon);```

Da passiert aber rein gar nichts, leider.

Kann mir jemand erläutern, woran es liegen kann?

PS: Aufgrund von weiterem Quelltext weiter unten, welcher darauf angewiesen ist, dass diese Methode static ist, ist und bleibt diese Methode static. :)

Gruß
Lukas

Dass das mit static ganz großer Mist ist haben wir dir ja nun schon das ein oder andere mal erklärt…

Zu deinen Icons: Wird die Methode überhaupt aufgerufen? Wann wird die Methode aufgerufen, und von wem? Stell gerne mal den restlichen Code rein damit man das Problem nachvollziehen kann.

Hallöle,

in meiner Mainmethode ist die Reihenfolge der Abläufe definiert:

        do{
        Spielstart.namensfrage();
        } while(spielernamenkorrekt == false);*/
        Spielstart.gastkartenmischen();
        Spielstart.laenderkartenmischen();
        Spielstart.spielfeldgenerieren();
        spielframe.setVisible(true);```

Also bei der Namensfrage fragt er die Spielernamen ab, dann mischt er die Gastkarten, dann die Länderkarten und dann generiert er das Spielfeld, das ist die Methode, in der ich drin bin.
Anschließend wird der frame sichtbar gemacht.

Also wird alles abgerufen, der Rest dieser Methode wird auch praktiziert. Die Methode existiert seit Monaten und arbeitet wie ein Schweizer Uhrwerk. ;) 

Ich weiß nun nur nicht, was er dagegen hat:
```Icon icon = new ImageIcon("/././resources/demo_CF.jpg");
            Spielfeld.spielfeldlabeltisch.get(n).setIcon(icon);```


Ach ähm, was ich noch sagen wollte. Es gibt Dreizehn Demobilder in dem Ordner. Ich hatte im Beispiel DE gesagt und dann im Quellcode CF geschrieben. Also daran liegt es jetzt nicht, die Datei ist vorhanden, hatte mich nur verschrieben. ;)

Gruß
Lukas

Ist das so ein Eclipse-Ratespiel, was ist Ordner und was Paket? :smiley:
Evtl. liegt das Bild ja in einem Ordner, der von der IDE als SRC-Ordner verwaltet wird, in diesem Fall darfst du keinen Filenamen angeben, sondern eine URL, welche du mit „getClass().getClassloader().getResource(“/path/name")" bekommst.

Hallöle,

okay okay, ich habs doch noch rausgekriegt. Ich hatte mir glücklicherweise schon einmal eine Methode geschrieben, die mir die URL anzeigt, wo es hinkommt.
Die Lösung ist das hier:

			Spielfeld.spielfeldlabeltisch.get(n).setIcon(icon);```
Wobei Dateipfad der entsprechende Platzhalter ist.

Also er scheint es zu nehmen. Weil er mir gleich das ganze Layout mit versaut.

Danach sieht es so aus:



Ich muss da noch herausfinden, wie ich dem sage, dass er die Labelgröße belässt und sich da mit gleicher Größe einfügt...

AU WEIA!!!
Wenn du jetzt das Ganze noch in Eclipse programmierst (oder auch ähnliche IDEs bzw. Hardcore im Editor) und “dateipfad” irgendwas mit “/src/paketname” beinhaltet, dann herzlichen Glückwunsch. Das Programm geht so spätestens dann auf die Bretter, wenn du es als Jar auf einem anderen Rechner startest.

[QUOTE=Spacerat]AU WEIA!!!
Wenn du jetzt das Ganze noch in Eclipse programmierst (oder auch ähnliche IDEs bzw. Hardcore im Editor) und “dateipfad” irgendwas mit “/src/paketname” beinhaltet, dann herzlichen Glückwunsch. Das Programm geht so spätestens dann auf die Bretter, wenn du es als Jar auf einem anderen Rechner startest.[/QUOTE]

Dateipfad sieht so aus:
String dateipfad = new File("").getAbsolutePath();

Das sollte also mit AbsolutePath überall funktionieren. Zumindest hat es das bisher sowohl auf nem Windoof, als auch auf dem Mac.

[QUOTE=FranzFerdinand]Dateipfad sieht so aus:
String dateipfad = new File("").getAbsolutePath();

Das sollte also mit AbsolutePath überall funktionieren. Zumindest hat es das bisher sowohl auf nem Windoof, als auch auf dem Mac.[/QUOTE]

Okay okay, Du hast Recht, in ner ausgeführten Jar-Datei geht das dann nicht mehr. Das ist doch eine Katastrophe.

Hat irgendwer einen adäquaten Plan, wie man Java beibringen kann, wo die Datei liegt und dass das Bild sich an die JLabel Größe anzupassen hat?
Ohne dieses Wissen kann ich das gesamte Projekt begraben.

Schöne Grüße
Lukas

Wäre ja schlimm, wenn nicht… :wink:

Zunächst erstmal, löse dich von „File“ bzw. Filesystemen und spezialisiere dich auf URLs, das ist einfacher, als es aussieht. Danach, hier entlang.

Hallöle, Hallöle,

es ist schön, dass es Leute gibt, die solche Blogeinträge hier veröffentlichen, Dankeschön. :slight_smile: Das ist ein Knackpunkt, der mir schon seit Ewigkeiten die Nerven raubt.

Aber ich muss eine Sache gestehen…
Ich kann das jetzt zwar verbauen, aber so ganz nachvollziehen, wieso es so läuft, wie es läuft kann ich nicht. Da fehlt mir wohl noch die Erfahrung, da muss ich mich noch reinlesen. Und was einbauen, was ich nicht kenne find ich schon nicht knorke. Aber okay.

Also, ich habe die Klasse BaseURL einmal mit in mein Verzeichnis übernommen.


import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
 
public final class BaseURL {
    private static final String JAR_SIG = ".jar!/";
    private static final String CONCAT = ".class";
    private static final File CURRENT = new File(".");
 
    /**
     * Gibt die Basis-URL des Archivs zurueck, in welchem sich die Klasse
     * "clazz" befindet. Aehnlich wie
     *   clazz.getProtectionDomain().getCodeSource().getLocation();
     * nur um einiges zuverlässiger, weil es auch dann eine URL zurueck-
     * gibt, wenn fuer die Klasse keine ProtectionDomain definiert wurde.
     *
     * @param clazz Die Klasse fuer welche die Basis-URL benoetigt wird
     * @return Archiv Basis-URL
     * @throws NullPointerException falls "clazz" null ist.
     */
    public static URL getJarBase(Class<?> CafeMain) {
        URL rc = CafeMain.getResource(CafeMain.getSimpleName() + CONCAT);
        String name = CafeMain.getName().replace('.', '/').concat(CONCAT);
        name = rc.toString().replace(name, "");
        try {
            rc = new URL(null, name);
            return rc;
        } catch (MalformedURLException e) {
            // should never happen
            throw new RuntimeException("jar dir could not be determined");
        }
    }
 
    /**
     * Ermittelt den Pfad des Archivs, in welchem sich "clazz" befindet.
     * Die Methode dient also hauptsaechlich zur Ermittlung von
     * Installationspfaden.
     * @param clazz Eine Klasse aus dem Archiv fuer welche der Pfad
     *              ermittelt werden soll.
     * @return Archiv-URL
     * @throws NullPointerException falls "clazz" null ist.
     */
    public static URL getCodeBase(Class<?> CafeMain) {
        URL rc = getJarBase(CafeMain);
        if (rc.getProtocol().equals("jar")) {
            String name = rc.toString();
            int i = name.indexOf(JAR_SIG);
            name = name.substring(4, i);
            try {
                rc = new URL(null, name);
                rc = new URL(rc, "./");
            } catch (MalformedURLException e) {
                // should never happen
                throw new RuntimeException("code base could not be determined");
            }
        }
        return rc;
    }
 
    /**
     * Gibt das Arbeitsverzeichnis in welchem die Anwendung ausgefuehrt wird
     * als URL zurueck.
     * @return URL Arbeitsverzeichnis
     */
    public static URL getDocumentBase() {
        try {
            String rc = getWorkingDir().toURI().toURL().toString();
            return new URL(null, rc.substring(0, rc.length() - 2));
        } catch (MalformedURLException e) {
            // should never happen
            throw new RuntimeException("document base could not be determined");
        }
    }
 
    /**
     * Gibt das Arbeitsverzeichnis in welchem die Anwendung ausgefuehrt wird
     * zurueck.
     * @return File Arbeitsverzeichnis
     */
    public static File getWorkingDir() {
        return getAbsoluteFile(CURRENT);
    }
 
    /**
     * Dies ist ein Workaround, der Dateisysteme berifft, in denen Links,
     * vorallem Verzeichnis-Links als Datei existieren (z.B. Windows ".lnk").
     * In Java werden solche Verzeichnis-Links teilweise als Verzeichnis
     * und teilweise als Datei betrachtet, was haeufig zu Problemen fuehrt.
     * Der Workaround ist noch nicht ganz perfekt.
     * @param f
     * @return
     */
    public static File getAbsoluteFile(File f) {
        try {
            f = f.getCanonicalFile();
        } catch (IOException e) {
            f = f.getAbsoluteFile();
        }
        return f;
    }
 
    /**
     * Gibt das Zielverzeichnis einer File-URL als File-Objekt zurueck.
     * @param u
     * @return File Zielverzeichnis einer File-URL
     */
    public static File URLtoFile(URL u) {
        if(!"file".equalsIgnoreCase(u.getProtocol())) {
            throw new IllegalArgumentException("protocol is not 'file'");
        }
        return new File(u.getFile());
    }
}```

Hierbei habe ich "clazz" (schreibt man Klassen nicht groß? Oder muss das jetzt mal so sein?) durch CafeMain ersetzt, meine Hauptklasse.

Und an der Stelle, wo man die Bilder einfügt kommt dann das hier:
```Icon icon = new ImageIcon(BaseURL.getWorkingDir()+"/resources/demo_DE2.jpg");
			Spielfeld.spielfeldlabeltisch.get(n).setIcon(icon);```

In Eclipse kann man das ohne Probleme ausführen. Aber beim Umwandeln in eine JAR kommt dann wieder der Fauxpas, leider kann er die Bilder nicht anzeigen.
Wahrscheinlich hab ich in der Bedingung wieder was unnötig verkompliziert. Oder eine falsche Methode benützt.

Du hast leider nur die Hälfte verstanden, aber das macht nichts.

  1. “clazz” ist (bzw. war ;)) nur ein Variablenname und als solcher “camelCase” geschrieben, also klein.
  2. “BaseURL.getWorkingDir()+”/resources/demo_DE2.jpg" kann und wird nicht funktionieren, weil man File-Objekte nicht mit Strings concatieren kann.
  3. “new ImageIcon()” funktioniert afaik auch mit URL-Parametern. Du musst dir also zunächst erstmal im Klaren darüber sein, wo du deine Resourcen für das laufende Programm parkst, dafür stehen Installations-, Arbeits- und/oder Klassenpfad zur Verfügung. In deinem Fall sieht es so aus, als wolltest du die Bilder nicht mit in das Jar übernehmen, also denke ich mal, dass der Installationspfad für dich in Frage kommt, also lautet der Aufruf für dich: "new ImageIcon(new URL(getCodeBase(Spielfeld.class), “resources/demo_DE2.jpg))”. Leider musst du auch hier die MalformedURLException abfangen und entsprechend auf eine solche reagieren. In diesem Fall aber ist es leider nicht mit “// should never happen” getan.
  4. Für den Fall, dass du die Bilder doch im Jar halten willst, kannst du entweder wie in 3. entsprechend mit “getJarBase()” verfahren, oder die URL mit “Spielfeld.class.getClassloader().getResource(”/resources/demo_DE2.jpg")" ermitteln.
  5. Spielfeld.class habe ich hier stellvertretend für jene Klasse verwendet, in der du diese Resourcen laden willst.

Hallöle Hallöle und Danke nochmals für Deine Antwort,

huch huch, 1. ist mir ja jetzt peinlich, Du hast recht. :wink:
Ich setze es in den Ursprungszustand zurück.

Ich würde jetzt an der Stelle wo ich bin folgendes ausprobieren:

				URL url = new URL(BaseURL.getCodeBase(Spielfeld.class), "resources/demo_DE2.jpg");
				System.out.println(url);
				Icon icon = new ImageIcon(url);
				Spielfeld.spielfeldlabeltisch.get(n).setIcon(icon);
			} catch(MalformedURLException e) {
				// da passiert noch irgendwas später	
			}```

Vielen dank für den Hinweis mit der Exception. ;) 
Es funktioniert insoweit schon einmal perfekt, insofern ich den `resources` Ordner in den bin Ordner verschiebe.
Der war vorher Parallel zu src und bin in einem Verzeichnis.
Die Konsole gibt mir auch folgenden Pfad dazu, kann man auch nachvollziehen:
```file:/Users/Lukas/Documents/Schule/Informatik/Seminarkurs/CafeInternationalGrafik/cafeint/bin/resources/demo_DE2.jpg```
Beim exportieren in eine JAR-Datei werden die jedoch nicht kopiert und dann läuft das wieder nicht.

Ich würde abschließend gerne wissen, wie ich das mit dem Bilderordner in Java respektive Eclipse am besten lösen sollte.

Vielen Dank!
Lukas :)

Das sollte man nie machen…!! Bei einem Projekt clear wird der bin Ordner komplett geleert. Dateien aus bin/ werden nicht in die JAR gepackt.

Lege den resources/ Ordner entweder in den src/ Ordner, oder lege den resources/ Ordner als weiteren source folder fest. Die IDE kopiert das dann automatisch nach bin/.

Deshalb frage ich ja nach.
Also ich hab das jetzt so gemacht:
Projekt/

  • src/
  • bin/
  • resources

Resources wurde in Eclipse als Quellenordner markiert. Ich kann Quellenordner da auch nur parallel von den anderen Ordnern anlegen und nicht direkt in src schieben.

Ich suche nun irgendwie eine Adäquate Lösung, wie ich irgendwie eine Lösung baue, die sowohl in Eclipse als auch in der JAR Datei dann korrekt angezeigt wird.

Wenn deine Ordnerstruktur so aussieht und resources/ ein Sourcefolder ist, dann ist der Pfad zum Bild folgender: /demo_DE2.jpg. Damit funktionierts dann auch in der JAR.