# Wie ein Hintergrundbild einfügen???



## Bisa (6. Jul 2010)

Hi Leute,
wir programmieren in der Schule zur Zeit mit BlueJ an einem Projekt und möchte in dieses nun eine Methode in die Klasse Leinwand einfügen, mit der man ein Hintergrundbild zurückgibt und  die man von STEUERUNG aus aufrufen kann, aber leider kann ich es nicht.

Hier mein Code der Klasse Leinwand:



```
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.Timer;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.util.*;


/**
 * Leinwand ist eine Klasse, die einfache Zeichenoperationen auf einer
 * leinwandartigen Zeichenfläche ermöglicht. Sie ist eine vereinfachte Version
 * der Klasse Canvas (englisch für Leinwand) des JDK und wurde speziell für das
 * Projekt "Figuren" geschrieben.
 * 
 * 
 * @author: Bruce Quig
 * @author: Michael Kölling (mik)
 * @author: Axel Schmolitzky
 * 
 * @version: 2006.03.30
 */
public class Leinwand{
    // Hinweis: Die Implementierung dieser Klasse (insbesondere die
    // Verwaltung der Farben und Identitäten der Figuren) ist etwas
    // komplizierter als notwendig. Dies ist absichtlich so, weil damit
    // die Schnittstellen und Exemplarvariablen der Figuren-Klassen
    // für den Lernanspruch dieses Projekts einfacher und klarer
    // sein können.

    private static Leinwand leinwandSingleton;

    /**
     * Fabrikmethode, die eine Referenz auf das einzige Exemplar dieser Klasse
     * zurückliefert. Wenn es von einer Klasse nur genau ein Exemplar gibt, wird
     * dieses als 'Singleton' bezeichnet.
     */
    public static Leinwand gibLeinwand() {
        if (leinwandSingleton == null) {
            leinwandSingleton = new Leinwand("CTB", 600, 500,
                    Color.white);
        }
        leinwandSingleton.setzeSichtbarkeit(true);
        return leinwandSingleton;
    }

    // ----- Exemplarvariablen -----

    private JFrame fenster;

    public CanvasPane canvas;

    private Graphics2D graphic;

    private Color hintergrundfarbe;
    
    private Image canvasImage;
    
    private JPanel steuerungOst,steuerungSued;

    private List<Object> figuren;

    private Map<Object, ShapeMitFarbe> figurZuShape;
    
    /**
     * Erzeuge eine Leinwand.
     * 
     * @param titel
     *            Titel, der im Rahmen der Leinwand angezeigt wird
     * @param breite
     *            die gewünschte Breite der Leinwand
     * @param hoehe
     *            die gewünschte Höhe der Leinwand
     * @param grundfarbe
     *            die Hintergrundfarbe der Leinwand
     */
    public Leinwand(String titel, int breite, int hoehe, Color grundfarbe) {
        fenster = new JFrame();
        canvas = new CanvasPane();
        fenster.getContentPane().add(canvas,BorderLayout.CENTER);
        JPanel panel1=new JPanel();
        panel1.setLayout(new BorderLayout());
        steuerungOst = new JPanel();
        steuerungSued = new JPanel();
        steuerungOst.setLayout(new BoxLayout(steuerungOst,BoxLayout.Y_AXIS));
        panel1.add(steuerungOst,BorderLayout.EAST);
        fenster.getContentPane().add(panel1,BorderLayout.EAST);
        fenster.getContentPane().add(steuerungSued,BorderLayout.SOUTH);
        fenster.setTitle(titel);
        canvas.setPreferredSize(new Dimension(breite, hoehe));
        hintergrundfarbe = grundfarbe;
        fenster.pack();
        figuren = new ArrayList<Object>();
        figurZuShape = new HashMap<Object, ShapeMitFarbe>();
    }

    /**
     * Setze, ob diese Leinwand sichtbar sein soll oder nicht. Wenn die Leinwand
     * sichtbar gemacht wird, wird ihr Fenster in den Vordergrund geholt. Diese
     * Operation kann auch benutzt werden, um ein bereits sichtbares
     * Leinwandfenster in den Vordergrund (vor andere Fenster) zu holen.
     * 
     * @param sichtbar
     *            boolean für die gewünschte Sichtbarkeit: true für sichtbar,
     *            false für nicht sichtbar.
     */
    public void setzeSichtbarkeit(boolean sichtbar) {
        if (graphic == null) {
            // erstmaliger Aufruf: erzeuge das Bildschirm-Image und fülle
            // es mit der Hintergrundfarbe
            Dimension size = canvas.getSize();
            canvasImage = canvas.createImage(size.width, size.height);
            graphic = (Graphics2D) canvasImage.getGraphics();
            graphic.setColor(hintergrundfarbe);
            graphic.fillRect(0, 0, size.width, size.height);
            graphic.setColor(Color.black);
        }
        fenster.setVisible(sichtbar);
    }

    /**
     * Zeichne für das gegebene Figur-Objekt eine Java-Figur (einen Shape) auf
     * die Leinwand.
     * 
     * @param figur
     *            das Figur-Objekt, für das ein Shape gezeichnet werden soll
     * @param farbe
     *            die Farbe der Figur
     * @param shape
     *            ein Objekt der Klasse Shape, das tatsächlich gezeichnet wird
     */
    public void zeichne(Object figur, String farbe, Shape shape) {
        figuren.remove(figur); // entfernen, falls schon eingetragen
        figuren.add(figur); // am Ende hinzufügen
        figurZuShape.put(figur, new ShapeMitFarbe(shape, farbe));
        erneutZeichnen();
    }

    /**
     * Entferne die gegebene Figur von der Leinwand.
     * 
     * @param figur
     *            die Figur, deren Shape entfernt werden soll
     */
    public void entferne(Object figur) {
        figuren.remove(figur); // entfernen,falls schon eingetragen
        figurZuShape.remove(figur);
        erneutZeichnen();
    }

    /**
     * Setze die Zeichenfarbe der Leinwand.
     * 
     * @param farbname
     *            der Name der neuen Zeichenfarbe.
     */
    public void setzeZeichenfarbe(String farbname) {
        if (farbname.equals("rot")) {
            graphic.setColor(Color.red);
        } else if (farbname.equals("schwarz")) {
            graphic.setColor(Color.black);
        } else if (farbname.equals("blau")) {
            graphic.setColor(Color.blue);
        } else if (farbname.equals("gelb")) {
            graphic.setColor(Color.yellow);
        } else if (farbname.equals("gruen")) {
            graphic.setColor(Color.green);
        } else if (farbname.equals("lila")) {
            graphic.setColor(Color.magenta);
        } else if (farbname.equals("weiss")) {
            graphic.setColor(Color.white);
        } else {
            graphic.setColor(Color.black);
        }
    }
    

    /**
     * Warte für die angegebenen Millisekunden. Mit dieser Operation wird eine
     * Verzögerung definiert, die für animierte Zeichnungen benutzt werden kann.
     * 
     * @param millisekunden
     *            die zu wartenden Millisekunden
     */
    public void warte(int millisekunden) {
        try {
            Thread.sleep(millisekunden);
        } catch (Exception e) {
            // Exception ignorieren
        }
    }

    /**
     * Zeichne erneut alle Figuren auf der Leinwand.
     */
    public void erneutZeichnen() {
        loeschen();
        for (Object figur : figuren) {
            figurZuShape.get(figur).draw(graphic);
        }
        canvas.repaint();
    }

    /**
     * Lösche die gesamte Leinwand.
     */
    private void loeschen() {
        Color original = graphic.getColor();
        graphic.setColor(hintergrundfarbe);
        Dimension size = canvas.getSize();
        graphic.fill(new Rectangle(0, 0, size.width, size.height));
        graphic.setColor(original);
    }

        /**
     * Fügt ein weiteres Steuerungselement in die rechte Steuerungsleiste ein.
     * @param  element  Das einzufügende Steuerungselement muss aus JComponent abgeleitet
     * sein. z. B. JButton, JComboBox. 
     */
    public void komponenteHinzufuegen(JComponent element, String position)
    {
        if (position=="rechts") steuerungOst.add(element);
        else if (position=="unten") steuerungSued.add(element);
        fenster.pack();
        canvas.repaint();
    }
    
    
    /***************************************************************************
     * Interne Klasse Zeichenflaeche - die Klasse für die GUI-Komponente, die
     * tatsächlich im Leinwand-Fenster angezeigt wird. Diese Klasse definiert
     * ein JPanel mit der zusätzlichen Möglichkeit, das auf ihm gezeichnet Image
     * aufzufrischen (erneut zu zeichnen).
     */
    private class CanvasPane extends JPanel
    {
        private static final long serialVersionUID = 20060330L;
        
        public void paint(Graphics g)
        {
            g.drawImage(canvasImage, 0, 0, null);
        }
    }
    
    /***************************************************************************
     * Interne Klasse ShapeMitFarbe - Da die Klasse Shape des JDK nicht auch
     * eine Farbe mitverwalten kann, muss mit dieser Klasse die Verknüpfung
     * modelliert werden.
     */
    private class ShapeMitFarbe {
        private Shape shape;

        private String farbe;

        public ShapeMitFarbe(Shape shape, String farbe) {
            this.shape = shape;
            this.farbe = farbe;
        }

        public void draw(Graphics2D graphic) {
            setzeZeichenfarbe(farbe);
            graphic.fill(shape);
        }
    }


}
```

Schon mal Danke im Voraus für jede Hilfe


----------



## headset (6. Jul 2010)

Möchtest du ein Foto einfügen oder de Hitergrund färben?


----------



## Bisa (6. Jul 2010)

Ich möchte ein Foto(jpg) als Hintergrund einfügen


----------



## iChaos (7. Jul 2010)

Hi
hatte letzten Freitag dasselbe Problem; nach langem Probieren und dank der Hilfe im Forum hier, löste ich es so:


```
frame.add(new TestPanel(Toolkit.getDefaultToolkit().getImage("backgroundBrush.jpg")));
```

Dort wo du das Frame definierst und Panels o.ä draufpackst, nimmst du den Toolkit.getDefault.Toolkit.getImage(bild, welches im gleichen verzeichnis wie das projekt sein sollte) Befehl, damit sollte es klappen. Danach nur noch mit der Paintmethode zeichnen.


```
private Image image;
public TestPanel(Image image){

	this.image = image;
	repaint();
}
protected void paintComponent(Graphics g){
            g.drawImage(image,startX,startY,endeX,endeY,this);
}
}
```


----------



## Marco13 (7. Jul 2010)

Etwas konkreter auf das Beispiel bezogen: Wann könnte grob sowas machen wie

```
private Image image; // set-Methode hierfür einbauen...

    public void erneutZeichnen() {
        loeschen();
        [b]hintergrundMalen();[/b] // Könnte ggf. auch in "löschen" gemacht werden
        for (Object figur : figuren) {
            figurZuShape.get(figur).draw(graphic);
        }
        canvas.repaint();
    }
 
    private void hintergrundMalen() {
        if (image != null) graphic.drawImage(image, 0, 0, null);
    }
```


----------



## Bisa (7. Jul 2010)

Ok,
das hab ich soweit verstanden, aber wie meinst du das mit der set-Methode?

so?

```
canvasImage = canvas.getToolkit().getImage("1.jpg");
```

Wäre nett, wenns jemand weis

MfG


----------



## Eldorado (7. Jul 2010)

```
public void setImage(Image image){
    this.image = image;
}
```
Das eine set-Methode . Diese wird dann so aufgerufen:

```
panel.setImage(Toolkit.getDefaultToolkit().getImage("backgroundBrush.jpg"));
```


----------



## Bisa (7. Jul 2010)

Ok, das hat zwar funktioniert, es wird auch übersetzt aber leider zeigt mir das Fenster am Schluss das Bild nicht an:bahnhof:

Habe nun in die hintergrundMalen()-Methode noch

```
System.out.println("Bild erfolgreich geladen");
```
eingebaut, damit ich weis ob die Methode schon ausgeführt wird.
Ergebnis: Bild erfolgreich geladen, aber kein sichtbares Bild???:L

Stehe im Moment total auf der Leitung...

MfG


----------



## L-ectron-X (7. Jul 2010)

Darauf habe ich schon gewartet...

In Eldorado's Code fehlt in der setImage()-Methode nach der Zuweisung noch die Aufforderung, mit repaint() neu zu zeichnen.
Außerdem hast du in deinem Code ganz oben in deinem von JPanel abgeleiteten CanvasPane nicht die paintComponent()-Methode überschrieben, sondern paint().

Ein weiteres mögliches Problem:
Das Laden von Bildern mit dem Toolkit wurde in AWT-Anwendungen praktiziert. Bei größeren Bildern kam es vor, dass sie nicht angezeigt wurden, obwohl sie offenbar gefunden und geladen wurden.
Grund dafür ist, dass die paint()-Methode zum Zeichnen schon vom Interpreter aufgerufen wurde, obwohl das Bild noch nicht fertig geladen wurde. Als Abhilfe kann man die Kontrolle über das Laden der Bilder an die Klasse _java.awt.MediaTracker_ übergeben, die erst die Kontrolle an das Programm zurück gibt, wenn das Bild auch wirklich gezeichnet werden kann.

In Swing-Anwendungen benutzt man zum Laden von Bildern die deutlich effizientere Klasse _javax.imageio.ImageIO_.
Beispiele findest du hier: Grafikdateien laden und anzeigen - Byte-Welt Wiki


----------



## Sarib Khan (19. Nov 2020)

headset hat gesagt.:


> Möchtest du ein Foto einfügen oder de Hitergrund färben?


Würde gerne auch wissen wie man allgemein die Hintergrundfarbe der Leinwand ändert z. B. Schwarz, rot etc...


----------



## Sarib Khan (19. Nov 2020)

headset hat gesagt.:


> Möchtest du ein Foto einfügen oder de Hitergrund färben?


Es ist 10 Jahre her haha aber würde gerne wissen wie man die Farbe der Leinwand ändert so z. B. Schwarz, Rot etc...


----------



## VfL_Freak (19. Nov 2020)

Moin,

das sollte über das "LookAndFeel" rsp. den UIManager klappen!

Siehe





						Openbooks. Rheinwerk-Bücher kostenlos online lesen. Ein Service des Rheinwerk Verlags
					






					openbook.rheinwerk-verlag.de
				











						javax.swing.UIManager.put java code examples | Tabnine
					

UIManager.put("control", ALUMINIUM_1);...   UIManager.put("info", BUTTER_1);...   UIManager.put("nimbusAlertYellow", BUTTER_2);




					www.codota.com
				




VG Klaus


----------



## kneitzel (19. Nov 2020)

Ja, Du hast einen Zombie zum Leben erweckt. 

Ansonsten hast Du generell die Methode setBackground: https://docs.oracle.com/javase/9/docs/api/javax/swing/JComponent.html#setBackground-java.awt.Color-

Damit kannst Du bei allen Swing Komponenten die Hintergrundfarbe setzen und diese wird dann für den Hintergrund genutzt. Setzt natürlich voraus, dass dieser gezeigt wird, also etwas nicht transparent ist...

Das wäre der Weg für ein einzelnes Element.


----------



## dzim (19. Nov 2020)

Bin nur hier zum trollen: Mit JavaFX wäre das nicht passiert...  

(Bin  schon wieder weg... 😂)


----------



## kneitzel (19. Nov 2020)

dzim hat gesagt.:


> Bin nur hier zum trollen: Mit JavaFX wäre das nicht passiert...
> 
> (Bin  schon wieder weg... 😂)


Wieso? Ist es da nicht möglich die Hintergrundfarbe zu setzen? Oder meinst Du, weil die Leute gleich daran scheitern, eine JavaFX Anwendung überhaupt zum laufen zu kriegen? 😂😂😂😂😂😂

Sorry, ich bin wieder gehässig ... aber generell: Wenn man Stift und Papier nimmt und das erst einmal durchspielt und ohne Java / JavaFX / Swing klar in Umgangssprache formuliert, was man überhaupt machen will, dann klappt das sowohl mit Swing als auch mit JavaFX ... (Das musste ja jetzt auch von mir kommen, oder? Ohne die Aussage würde ich eure Erwartungshaltung nicht erfüllen ...

Edit: Was habe ich beim posten für eine Meldung bekommen? "kneitzel trifft Zombi-Thread kritisch, Zombi Thread stirbt!" ... also haben wir es geschafft?


----------



## dzim (19. Nov 2020)

Touché.   



kneitzel hat gesagt.:


> Ist es da nicht möglich die Hintergrundfarbe zu setzen? Oder meinst Du, weil die Leute gleich daran scheitern, eine JavaFX Anwendung überhaupt zum laufen zu kriegen?


Doch (easy-peasy)! Autsch, aber ja (ich weiss nur nicht, was genau daran so schwer ist 🤷‍♂️).



kneitzel hat gesagt.:


> Wenn man Stift und Papier nimmt und das erst einmal durchspielt und ohne Java / JavaFX / Swing klar in Umgangssprache formuliert, was man überhaupt machen will, dann klappt das sowohl mit Swing als auch mit JavaFX


Schon, aber es bleibt der Faktor, dass man die APIs etwas kennen muss. Es ist - denke ich - eigentlich nie wirklich schwer. Aber wenn man keine Ahnung hat, wie man zum Ziel kommen soll, stellt einen das vor hohe Hürden.
Aber daran wächst man ja eigentlich nur.


----------



## kneitzel (19. Nov 2020)

Ich wollte das nicht wirklich diskutieren sondern nur den Clown rauslassen 

Aber ich bin bei Dir - es kann sehr einfach sein. Ich sehe da auch nicht wirklich etwas schwieriges. Wobei ich einige Stolpersteine sehe, wie z.B. die java.com Webseite. (Ich brauche Java, also gehe ich auf java.com - und schon habe ich ein JRE in Version 8 und wundere mich über Probleme ... Aber was erwartet man auch von Oracle? Wer die Oracle Installer für Windows kennt (oder kannte? Ist ja evtl. besser geworden), der hat eh eine klare Meinung zu dieser Firma ... Oracle Produkte kommen auf meinem PC nur, wenn es sich nicht vermeiden lässt ... Aber egal ...)

Dann die Thematik mit dem Einbinden der JavaFX Module .... 

Aber das sind Dinge, die aus meiner Sicht die IDE abfangen sollte. Ich bin da ja von IntelliJ total überzeugt:
Einfach IntelliJ installieren - vergiss irgendwelche Java Installationen ... kann man alles mit IntelliJ handhaben - und das ohne Installationen im System durchzuführen! (Toolbox nutzen -> dann landet IntelliJ im Homeverzeichnis. Die JDKs landen in ~/.jdks u.s.w. .... Projekte bekommen das JDK, das sie brauchen... wenn es fehlt, dann bietet IntelliJ sofort sauber eine Lösung ... 

Dann Gradle oder Maven - auch Anfänger können das schnell nutzen. Zu viel muss man ja nicht wissen - einfach paar Zeilen kopieren und gut ist es...

Aber egal - das war nicht das Thema aber ich bin ganz bei Dir ... und die Entscheidung zwischen Swing und JavaFX ist auch einfach. Auf die deklarativen UIs will man ja nicht wirklich verzichten. MVC bei Desktop Apps ist zwar mangelhaft, aber da würde ich dann mittels MVVM vorgehen mit mvvmFX ... wobei man natürlich auch mit dem MVC Pattern (unsauber) arbeiten kann ...


----------



## mihe7 (20. Nov 2020)

Sarib Khan hat gesagt.:


> Würde gerne auch wissen wie man allgemein die Hintergrundfarbe der Leinwand ändert z. B. Schwarz, rot etc...


Da man ja nie weiß, wer hier alles mitliest, ein wichtiger Hinweis: gold geht nicht. 

Nachtrag: @dzim selbst mit Swing nicht.


----------



## dzim (20. Nov 2020)

Mit JavaFX geht das *ALLES*!!!!11!!!elf!


----------

