Swing Bilder überlagern

DaCrazyJavaExpert

Bekanntes Mitglied
Guten Tag!
Ich habe ein GUI an dem ich nun schon seit 3 Tagen hänge und nichtmal zur "Eventzuteilung" gekommen bin.
Mein Problem sind die Bilder. Ich schaffe es nicht sie zu überlagern. Das Label 'labelBackground' soll der Hintergrund sein. Die anderen Labels sollen auf dem Hintergrund nebeneinander liegen, biss auf das Label 'labelMessage' das will ich weiter unten, aber immernoch über dem Hintergrund haben. So sieht meine jetziger Code aus (Die ausgeklammerten Codezeilen waren klägliche Versuche von mir):
Java:
package de.m_ver.minigamecollector.scheresteinpapier;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;

public class SchereSteinPapierGUI extends JFrame {
    public SchereSteinPapierGUI() {
        super("Schere Stein Papier");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocation(450, 0);
        this.initialisiereKomponenenten();
        this.ordneKomponenten();
        this.setSize(550, 735);
    }

    private JLabel labelBackground;
    private JLabel labelScissors;
    private JLabel labelStone;
    private JLabel labelPaper;
    private JLabel labelMessage;
    private ImageIcon iconBackground;
    private ImageIcon iconScissors;
    private ImageIcon iconStone;
    private ImageIcon iconPaper;
    private JLayeredPane layeredPane;

    private void initialisiereKomponenenten() {
        this.iconBackground = new ImageIcon("images/grundSSP.png");
        this.iconScissors = new ImageIcon("images/schere.png");
        this.iconStone = new ImageIcon("images/stein.png");
        this.iconPaper = new ImageIcon("images/papier.png");
        this.labelBackground = new JLabel(iconBackground);
        this.labelBackground.setOpaque(true);
        this.labelScissors = new JLabel(iconScissors);
        this.labelScissors.setOpaque(true);
        this.labelStone = new JLabel(iconStone);
        this.labelStone.setOpaque(true);
        this.labelPaper = new JLabel(iconPaper);
        this.labelPaper.setOpaque(true);
        this.labelMessage = new JLabel("MESSAGE");
        this.labelMessage.setOpaque(true);
       
        //ordneKomponenten();
    }

    private void ordneKomponenten() {
        this.getContentPane().setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;
        c.insets = new Insets(4, 4, 4, 4);
        c.gridx = 0;
        c.gridy = 1;
        c.gridwidth = 30;
        c.gridheight = 40;
        this.getContentPane().add(labelBackground, c);
        c.gridx = 4;
        c.gridy = 4;
        c.gridwidth = 6;
        c.gridheight = 6;
        this.getContentPane().add(labelScissors, c);
        c.gridx = 8;
        this.getContentPane().add(labelStone, c);
        c.gridx = 16;
        this.getContentPane().add(labelPaper, c);
        c.gridx = 2;
        c.gridy = 30;
        c.gridwidth = 1;
        c.gridheight = 1;
        this.getContentPane().add(labelMessage, c);
       
        /*this.labelBackground.setBounds(0, 0, 550, 735);
        this.labelScissors.setBounds(175, 20, 15, 15);
        this.labelStone.setBounds(350, 20, 15, 15);
        this.labelPaper.setBounds(520, 20, 15, 15);
        this.labelMessage.setBounds(225, 100, 1, 1);
       
        this.layeredPane = new JLayeredPane();
        this.layeredPane.add(this.labelBackground, 0);
        this.layeredPane.add(this.labelScissors, 1);
        this.layeredPane.add(this.labelStone, 2);
        this.layeredPane.add(this.labelPaper, 3);
        this.layeredPane.add(this.labelMessage, 4);
        this.getContentPane().add(this.layeredPane); */
    }

    public void start() {
        this.setVisible(true);
    }
}

Und so sieht die Main aus (nicht sehr besonders):
Java:
package de.m_ver.minigamecollector.main;

import de.m_ver.minigamecollector.scheresteinpapier.SchereSteinPapierGUI;

public class Main {

    public static void main(String[] args) {
        SchereSteinPapierGUI schereSteinPapierGUI = new SchereSteinPapierGUI();
        schereSteinPapierGUI.start();
    }

}

Also mein eigentliches Problem ist es, die JLabel übereinander zu bekommen. Danke für Hilfe im Vorraus!
 
Wie wäre es denn mit folgender Lösung:

Füg deinem JFrame ein JPanel als eine Art contentPane hinzu, dessen #paintComponent(Graphics) Methode du überschreibst und so dein Hintergrundbild zeichnen lässt.
Diesem JPanel kannst du dann deine JLabels adden, die die Bilder enthalten. So sind alle Komponenten über dem Hintergrundbild.
 
Wie wäre es denn mit folgender Lösung:

Füg deinem JFrame ein JPanel als eine Art contentPane hinzu, dessen #paintComponent(Graphics) Methode du überschreibst und so dein Hintergrundbild zeichnen lässt.
Diesem JPanel kannst du dann deine JLabels adden, die die Bilder enthalten. So sind alle Komponenten über dem Hintergrundbild.
Und wie überschreibe ich diese Methode? Ich habs so versucht (klappt aber nicht so wirklich):
Java:
package de.m_ver.minigamecollector.scheresteinpapier;

import java.awt.Graphics;

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

public class JPanelOverlay extends JPanel {
   @Override
   protected void paintComponent(Graphics g) {
       super.setBackground(((new JLabel(new ImageIcon("images/grundSSP")));
       super.paintComponent(g);
   }
}
}
So, wie setze ich denn den Hintergrund in mein image? setBackground() nimmt ja leider nur Fargben an. Ich weiß Tatsächlich nicht wie ich weiter vorgehen soll.
 
Zuletzt bearbeitet:
Ok, man muss aber noch ein ImageObserver eingeben und ich weiß nicht genau was das ist, hab es durch Google jetzt auch nicht wirklich herrausfinden können. Da stand ich muss da einfach die Komponente eingeben auf der ich zeichne, das ist doch das JLabel? Oder? Und muss ich das Image (erster Parameter) mit new ImageIcon("images/grundSSP") referenzeiren? Danke im Vorraus!
Java:
public class JPanelOverlay extends JPanel {
    @Override
    protected void paintComponent(Graphics g) {
        g.drawImage(new ImageIcon("grundSSP.png"), 550, 735, JLabel); //Habs jetzt grade so.
        super.paintComponent(g);
    }
}

#EDIT: Nun hab ich auch gesehen, dass ImageObserver mit this gefüllt werden kann wenn die Klasse von einer Klasse, welche von Compononent erbt, ableitet, was JPanel in diesem Fall tut, trotzdem wird 'this' vom Compiler nicht angenommen.
 
Zuletzt bearbeitet:
Ah ok ich habs jetzt geschafft, allerdings weiß ich jetzt nicht genau was in die methode getSourse von Image als rückgabewert geschrieben werden muss und was der Rückgabewert der Methode getGraphiks sein muss.
 
Ok, danke!
Also das hier ist die Klasse die von JPanel erbt, wo ich diese paintComponent().Methode überschreibe:
Java:
package de.m_ver.minigamecollector.scheresteinpapier;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.io.File;

import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class JPanelOverlay extends JPanel {
   
    @Override
    protected void paintComponent(Graphics g) {
        g.drawImage(new Image() {
           
            @Override
            public int getWidth(ImageObserver observer) {
                return 550; // Hier vermute ich einfach mal, dass hier die Breite hinsoll...
            }
           
            @Override
            public ImageProducer getSource() {
                return getSource(); // hier weiß ich nicht was als return-Wert hinsoll
            }
           
            @Override
            public Object getProperty(String name, ImageObserver observer) {
                return 0; // hier weiß ich nicht was als return-Wert hinsoll
            }
           
            @Override
            public int getHeight(ImageObserver observer) {
                return 735; //... und hier die Höhe des Bildes
            }
           
            @Override
            public Graphics getGraphics() {
                return null; // hier weiß ich nicht was als return-Wert hinsoll
            }
        }, 550, 735, this);
        super.paintComponent(g);
    }
   
}

Hab ich da was falsch gemacht?
Danke weiterhin, ohne dich äre ich bis hierhin vollkommen ausgeliefert 😀
 
  1. super.paintComponent(g); sollte das erste sein was du in der paintComponent Methode aufrufst
  2. Image kann, wie du vielleicht gemerkt hast, nicht instanziiert werden, da sie abstrakt ist. Anstatt eine neue Instanz zu erstellen musst du dein Bild ins Programm laden. Dazu gibt es die Methode ImageIO#read die du dir mal anschauen solltest. Die Methode gibt ein BufferedImage zurück, welches du dir in einer Instanz abspeichern kannst. Diese Instanz übergibst du dann der drawImage() Methode übergeben.
 
So, dass hier hab ich schon. Und yay, es werden keine Fehler angezeigt. 🙂 Allerdings wird mein Bild nicht angezeigt 🙁
Hier ist der jetztige Code:
Java:
package de.m_ver.minigamecollector.scheresteinpapier;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class JPanelOverlay extends JPanel {
  

  
    private BufferedImage imageBackground;;

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
      
        this.imageBackground = null;
        try {
            imageBackground = ImageIO.read(new File("images/grundSSP.png"));
        } catch (IOException e) {
            System.out.println("Bild konnte nicht geladen werden.");
        }
      
        g.drawImage(imageBackground, 550, 735, this);
    }
  
}
 
Hätt ich bloß mal nachgedacht 😕. Daran hats gelegen. Jetzt wird das JPanel endlich angezeigt! 🙂
Doch jetzt hab ich ein neues Problem 🙁. WIe ordne ich die einzelnen Komponenten im JPanel an? Ich habe es mit einem GridBagLayout probiert, doch irgendwie will es nicht so wie ich möchte, es wird nämlich gar nichts mehr angezeigt. Wenn man das GridBagLayout wegdenkt, und die eingeklammerten Codezeilen ausklammert, werden die Komponenten (JLabel's) immerhin angezeigt, allerdings ohne Layout, einfach in einer Reihe. Hier der Code:
Java:
public class SchereSteinPapierGUI extends JFrame {
    public SchereSteinPapierGUI() {
        super();
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocation(450, 0);
        this.initialisiereKomponenenten();
        this.ordneKomponentenJPanelOverlay();
        this.setSize(550, 735);
    }

    private JPanelOverlay panelOverlay;
    private JLabel labelScissors;
    private JLabel labelStone;
    private JLabel labelPaper;
    private JLabel labelMessage;
    private ImageIcon iconScissors;
    private ImageIcon iconStone;
    private ImageIcon iconPaper;

    private void initialisiereKomponenenten() {
        this.iconScissors = new ImageIcon("images/schere.png");
        this.iconStone = new ImageIcon("images/stein.png");
        this.iconPaper = new ImageIcon("images/papier.png");
        this.panelOverlay = new JPanelOverlay();
        this.labelScissors = new JLabel(iconScissors);
        this.labelScissors.setOpaque(false);
        //this.panelOverlay.add(labelScissors);
        this.labelStone = new JLabel(iconStone);
        this.labelStone.setOpaque(false);
        //this.panelOverlay.add(labelStone);
        this.labelPaper = new JLabel(iconPaper);
        this.labelPaper.setOpaque(false);
        //this.panelOverlay.add(labelPaper);
        this.labelMessage = new JLabel("MESSAGE");
        this.labelMessage.setOpaque(false);
        //this.panelOverlay.add(labelMessage);
    }

    private void ordneKomponentenJPanelOverlay() {
    this.panelOverlay.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
   
    c.fill = GridBagConstraints.VERTICAL;
    c.insets = new Insets(50, 50, 50, 50);
    c.gridx = 0;
    c.gridy = 0;
    this.panelOverlay.add(this.labelScissors, c);
   
    c.gridx = 1;
    c.gridy = 0;
    this.panelOverlay.add(this.labelStone, c);
   
    c.gridx = 2;
    c.gridy = 0;
    this.panelOverlay.add(this.labelPaper, c);
   
    c.gridx = 1;
    c.gridy = 2;
    this.panelOverlay.add(this.labelMessage, c);
    }

    public void start() {
        this.setVisible(true);
    }
}

Ich wusste gar nicht das GUI so anstrengend sein kann... >.<
Danke im Vorraus!
 
Ja GUI Programmierung mit Java ist eine Sache für sich. Aber auch da kann man sich rein denken. 😛

Wie solls denn am Ende aussehen? Ich denke man kann ein schöneres Layout als das GridBagLayout nehmen.
 
Ja GUI Programmierung mit Java ist eine Sache für sich. Aber auch da kann man sich rein denken. 😛

Wie solls denn am Ende aussehen? Ich denke man kann ein schöneres Layout als das GridBagLayout nehmen.
Ich dachte das GridBagLAyout wäre so das schönste was es so gibt, also das mit den meisten Möglichkeiten. :O
Ok, hier zeige ich jetzt dann mal meine Vorstellung des Fertigen GUI's:
Hier so sieht es ohne GridBagLayout aus, also nur mit den Ausgeklammerten, zurzeit noch eingeklammerten Codezeilen:
show.php

Das GUI mit GridBagLAyout ohne die Ausgeklammerten Codezeilen ist wie gesagt einfach ganz leer.

Das GUI, wie es aussehen soll (Mit GIMP erstellt):
show.php

Es soll mal ein Schere, Stein, Papier Spiel draus werden. Wollte ich als Einstige in die GUI-Programmierung machen, erwies sich als schwer! 😛 (MESSAGE soll später die Nachricht sein welche ausgibt ob man gewonnen, verloren, oder ob Gleichstand hat/ist.
Auf die Oberen Labels soll geklickt werden können, wass ich mit dem ClickEvent später (versuchen/) machen werde. 🙂 Soviel zu meinem Plan. Sitze by the way schoon seit fast ner woche, glaub ich an diesem einen GUI! Ich hoffe ich werd besser, sonst wärs glaub ich mal nicht so gut 7 Tage an einem einzigen Frame zu sitzen.
Dankö!
 
Ich dachte das GridBagLAyout wäre so das schönste was es so gibt, also das mit den meisten Möglichkeiten. :O
Nun ja, es hat viele Möglichkeiten - kann einem aber auch zur Weißglut bringen 😛

Wenn du es mit einem GridBagLayout machen willst kannst du es mit folgenden Constraints tun:
Code:
                  gridx  gridy  weightx  weighty
Schere:             0       0      1        1
Stein:              1       0      1        1
Papier:             2       0      1        1
MESSAGE:            1       1      1        1

Das würde ca. deinen Vorstellungen entsprechen, denke ich 😉
 
Ja ich habs ja mit nem GridBagLAyout gemacht, allerdings wird da halt nur ein leeres Fenster angezeigt.

#Edit: Doch nicht 😛. Hab vergessen das JPanelOverlay dem Frame zu adden.
 
Zuletzt bearbeitet:
Neues Problem:
Die Komponeneten in nur einem einzigen Bereich und können durch ändern der Werte von gridx/y/usw., nicht verschoben werden. So sieht das jetztzige Fenster aus:
Sie sind nur in diesem einzigen Viereck in der Mitte
 
Jaaaaaa, FERTIG! Es geht, dass komplette Programm läuft 😀. Ich bin so froh. Ich liebe diese Gefühl ein Programm fertig gestellt zu haben.
Großes Danke an dich @Robat <3. Ohne dich wäre ich längst nicht so weit. 😀 Ok jetzt brauch ich ne Idee für die nächsten Tage, mal schaun was mir so einfällt 🙂.

PS: Kann es sei, dass dies hier die längste Koservation zwischen 2 Personen in diesem Forum war? 😛 >,<
 

Neue Themen


Zurück
Oben