# Mit Swing eine Grafische Oberfläche erstellen



## Battleju (30. Jul 2017)

Ich habe vor ein spiel zu entwickeln, bei dem es einen Spieler gibt, der ein Haus vor Zombies verteidigen muss. 
Grafisch habe ich das dann so realisiert, dass ich in einem JFrame Textfelder in einem GridLayout angeordnet habe, die dann ein Spielfeld ergeben. In diesen Textfeldern lasse ich dann Bilder painten. 

Nun läuft das ganze so, dass die einzelnen leeren weißen Felder zu sehen sind. Auf den Koordinaten wo dann der Player steht ist dann Anstelle eines leeren Feldes das Bild des Spielers. 
Jetzt möchte ich eine Umgebung hinzufügen, indem ich einfach ein Hintergrundbild in das Frame einfüge. Und das ist das Problem. Ich habe den Code dementsprechend bearbeitet. Jedoch gibt es weder ein Hintergrund zu sehen noch irgendwelche Fehlermeldungen die mir weiterhelfen. 
Ich hoffe mir kann jemand helfen das Problem zu lösen. 

Dann habe ich noch die Frage, ob es einfachere Grafiklösungen gibt, bzw. Grafiklösungen mit denen man mehr Möglichkeiten hat die Spielwelt grafisch darzustellen und trotzdem nicht viel schwieriger sind.

Hier ist der Code, der Fehlerhaft ist:

```
package swing;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

import org.eclipse.jdt.annotation.Nullable;

import world.Koordinaten;
import world.Koordinaten.Ebene;
import world.MyWorldController;
import world.WeltAdapter;
import world.WorldObjekt;

/**
* Swing-Frame
*/
public class SwingWelt implements WeltAdapter {
    private static int mRows = 20;
    private static int mCols = 20;
    private static final int GAP = 0;
    private Map<Koordinaten, WorldComponent> mBasisWorldObjekts = new HashMap<>();
    private Map<Koordinaten, WorldComponent> mTopWorldObjekts = new HashMap<>();
    private MyWorldController mWorld;
    private BufferedImage imgObject;

    public SwingWelt() {
        this(mRows, mCols);
    }

    public SwingWelt(int rows, int cols) {
        try {
            imgObject = ImageIO.read(new File("src/textures/Background.jpg"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        JFrame frame = new JFrame("Stack");
        JPanel mainPanel = new JPanel(new GridLayout(rows, cols, GAP, GAP)){
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                if (imgObject != null) {
                    g.drawImage(imgObject, 0, 0, 600, 600, null);
                }
            }
        };
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {
                Koordinaten koordinaten = new Koordinaten(row, col);
                WorldComponent textfield = (new WorldComponent(Ebene.Basis));
                mBasisWorldObjekts.put(koordinaten, textfield);
                textfield.setFocusable(false);
                mainPanel.add(textfield);
            }
        }
       
        
        mWorld = new MyWorldController(this, rows, cols);
        mainPanel.addKeyListener(new StackKeyListener(mWorld));
        mainPanel.setFocusable(true);
        mainPanel.requestFocusInWindow();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.out.println("Closed");
                // Alle laufenden WorldObjekte beenden
                mWorld.cancel();
                e.getWindow().dispose();
            }
        });
        frame.add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    @Override
    public synchronized void notifyWorldChanged() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                for (int row = 0; row < mRows; row++) {
                    for (int col = 0; col < mCols; col++) {
                        for (Map.Entry<Koordinaten, WorldComponent> cursor : mBasisWorldObjekts.entrySet()) {
                            WorldObjekt obj = mWorld.getWorldObjekt(cursor.getKey());
                            WorldComponent field = cursor.getValue();
                            field.setWorldObjekt(obj);
                        }
                    }
                }
            }
        });
    }

    @Override
    public synchronized void notifyPositionChanged(Koordinaten koordinaten) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                @Nullable
                WorldObjekt obj = mWorld.getWorldObjekt(koordinaten);
                WorldComponent field;
                switch (koordinaten.EBENE) {
                case Top:
                    field = mTopWorldObjekts.get(koordinaten);
                    break;
                default:
                    obj = mWorld.getWorldObjekt(koordinaten);
                    field = mBasisWorldObjekts.get(koordinaten);
                }
                field.setWorldObjekt(obj);
            }
        });
    }
   
    private class TransparentTextField extends JTextField {
        Color mColor = new Color(0, 0, 0, 0);

        public TransparentTextField(String text) {
            super(text, 3);
            setHorizontalAlignment(JTextField.CENTER);
            setForeground(Color.RED);
            setBackground(mColor);
            setOpaque(false);
        }

        @Override
        public void paintComponent(Graphics g) {
            g.setColor(mColor);
            Rectangle r = g.getClipBounds();
            g.fillRect(r.x, r.y, r.width, r.height);
            super.paintComponent(g);
        }
    }
}
```

Danke für die Hilfe im voraus.

lg bttl


----------



## Blender3D (30. Jul 2017)

Battleju hat gesagt.:


> Dann habe ich noch die Frage, ob es einfachere Grafiklösungen gibt, bzw. Grafiklösungen mit denen man mehr Möglichkeiten hat die Spielwelt grafisch darzustellen und trotzdem nicht viel schwieriger sind.


Eine wirklich flexible Lösung ist: Ein BufferdImage in das man alle Grafik Ausgaben macht und dieses nach jeder Änderung der Spielesituation neu zeichnen lässt.

```
public class GamePanel extends JPanel{
     private final GraphicsConfiguration gfxConf = GraphicsEnvironment
                          .getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
     private BufferedImage imageBuffer = null;

     @Override
     protected void paintComponent( Graphics g ){
         if( imageBuffer == null || imageBuffer.getWidth() != getWidth() || imageBuffer.getHeight() != getHeight() ){
             imageBuffer = gfxConf.createCompatibleImage( getWidth(), getHeight() );
         }
     g.drawImage( imageBuffer, 0, 0, this );
        }
     public void updateGraphics(){
         Graphics g = imageBuffer.createGraphics();
         // do grapical manipulation here.
         ..
         repaint();
     }
}
```
Das ist einfacher und flexibler als Dein Ansatz


----------

