JPanel austauschen und Focus geben

Diskutiere JPanel austauschen und Focus geben im AWT, Swing, JavaFX & SWT Bereich.
A

Amaisenpär

Hi Leute,

Ich habe Snake geklont und möchte gerne, dass sich zunächst ein Menu-Fenster öffnet, wenn das Programm startet. Im Menu sollen verschiedene Buttons sein, mit denen man z.B. das Spiel starten, die Spielanleitung oder die Highscores einsehen kann. Das Menüpanel habe ich bereits erstellt. Wenn ich den Button "play" anklicke erscheint das JPanel "board", auf dem das Spiel stattfindet und das Menu verschwindet. Allerdings lässt sich die Snake nicht lenken und reagiert auf nichts. Liegt es eventuell daran, dass das JPanel keinen Focus hat? Ich habe schon probiert den Focus auf das board zu bekommen, jedoch ohne Erfolg. Vielleicht liegt der Fehler ja auch ganz wo anders?

Ich bin für jeden Tipp dankbar!


Hier ist die Klasse "Snake":
Code:
package Snake;

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JTabbedPane;

public class Snake {
   
    static Menu menu;
    Frame frame;
    Snake() {
       
        frame = new Frame();
        menu = new Menu(frame);
        frame.setSize(900, 600);
        frame.add(menu);
        frame.setVisible(true);
     
    }
   
    public static void main(String[] args) {
       
        EventQueue.invokeLater(() -> {
            new Snake();
         
        });
    }
}
Das ist die Klasse Frame:
Code:
package Snake;

import javax.swing.JFrame;

public class Frame extends JFrame{
   
    Board board;
   
    Frame(){
   
    setSize(900, 600);
    setVisible(true);
}

void initUI() {
   
    board = new Board();
    board.setFocusable(true);
    board.requestFocusInWindow();
    add(board);
   
   setTitle("Snake");
   setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}

Das ist die Klasse Menu:
Code:
package Snake;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JButton;
import javax.swing.JPanel;

public class Menu extends JPanel{

    JButton shop, play, instructions, highscores, groups, quit;
   
    Menu(Frame frame){
        setLayout(null);
        shop = new JButton("SHOP");
        play = new JButton("PLAY");
        instructions = new JButton("INSTRUCTIONS");
        highscores = new JButton("HIGHSCORES");
        groups = new JButton("GROUPS");
        quit = new JButton("QUIT");
       
        shop.setBounds(0, 0, 150, 30);
        play.setBounds(0, 30, 150, 30);
        instructions.setBounds(0, 60, 150, 30);
        highscores.setBounds(0, 90, 150, 30);
        groups.setBounds(0, 120, 150, 30);
        quit.setBounds(0, 150, 150, 30);
       
       
        play.addMouseListener(new MouseListener() {

            @Override
            public void mouseClicked(MouseEvent e) {
               
                Snake.menu.setVisible(false);
                Snake.menu.invalidate();
                Snake.menu.validate();
                frame.initUI();
               
            }

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

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

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

            @Override
            public void mouseReleased(MouseEvent e) {
                // TODO Auto-generated method stub
               
            }
           
        });
       
        quit.addMouseListener(new MouseListener() {

            @Override
            public void mouseClicked(MouseEvent e) {
                System.exit(0);
               
            }

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

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

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

            @Override
            public void mouseReleased(MouseEvent e) {
                // TODO Auto-generated method stub
               
            }
           
        });
       
       
       
        add(play);
        add(shop);
        add(instructions);
        add(highscores);
        add(groups);
        add(quit);
    }

   

}
Und hier ist die Klasse Board (Ich weiss, die Klasse ist ziemlich umfangreich. Ich denke nicht, dass hier der Fehler liegt, nur um auf Nummer sicher zu gehen stelle ich sie hier vollständig ein.

Code:
package Snake;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

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

public class Board extends JPanel implements ActionListener {
   
    int viagra_counter = 0;
    boolean viagra_effect = false;
    JLabel score_panel = new JLabel("0");
    int security = 0;
    static boolean snakeStandart = true;
    static boolean snakeRed = false;
   
    int speed_moves;
    int random;
    int herpes_x, herpes_y;
    int scissors_x, scissors_y;
    int car_x, car_y;
    int viagra_x, viagra_y;
   
    private final int B_WIDTH = 900;
    private final int B_HEIGHT = 600;
    private final int DOT_SIZE = 10;
    private final int ALL_DOTS = 900;
    private final int RAND_POS = 29;
    private int DELAY = 300;
   
    private final int x[] = new int[ALL_DOTS];
    private final int y[] = new int[ALL_DOTS];

    private int dots;
    double score = dots;
    private int apple_x;
    private int apple_y;
   

    private boolean leftDirection = false;
    private boolean rightDirection = true;
    private boolean upDirection = false;
    private boolean downDirection = false;
    private boolean inGame = true;

    private Timer timer;
    private Image ball;
    private Image apple;
    private Image head;
    private Image red;
    private Image lightRed;
    private Image herpes;
    private Image scissors;
    private Image viagra;
    Image car;

    public Board() {
       
        initBoard();
    }
   
    private void initBoard() {

        addKeyListener(new TAdapter());
        setBackground(Color.black);
        setFocusable(true);

        setPreferredSize(new Dimension(B_WIDTH, B_HEIGHT));
       
        score_panel.setBounds(0,  0,  100,  20);
        add(score_panel);
        loadImages();
        initGame();
     
    }

    private void loadImages() {

        ImageIcon iid = new ImageIcon("C:\\Users\\versp\\Pictures\\Camera Roll\\FLESH.png");
        ball = iid.getImage();

        ImageIcon iia = new ImageIcon("C:\\Users\\versp\\Pictures\\Camera Roll\\Tauziehen1.png");
        apple = iia.getImage();
       
        ImageIcon iiv = new ImageIcon("C:\\Users\\versp\\Pictures\\Camera Roll\\VIRUS.png");
        herpes = iiv.getImage();

        ImageIcon iih = new ImageIcon("C:\\Users\\versp\\Pictures\\Camera Roll\\FLESH.png");
        head = iih.getImage();
       
        ImageIcon rot = new ImageIcon("C:\\Users\\versp\\Pictures\\Camera Roll\\RED.png");
        red = rot.getImage();
       
        ImageIcon hellrot = new ImageIcon("C:\\Users\\versp\\Pictures\\Camera Roll\\LIGHT_RED.png");
        lightRed = hellrot.getImage();
       
        ImageIcon sci = new ImageIcon("C:\\Users\\versp\\Pictures\\Camera Roll\\SCISSORS.png");
        scissors = sci.getImage();
       
        ImageIcon auto = new ImageIcon("C:\\Users\\versp\\Pictures\\Camera Roll\\CAR.png");
        car = auto.getImage();
       
        ImageIcon vgra = new ImageIcon("C:\\Users\\versp\\Pictures\\Camera Roll\\VIAGRA.png");
        viagra = vgra.getImage();
    }

    private void initGame() {

        dots = 3;

        for (int z = 0; z < dots+1; z++) {
            x[z] = 50 - z * 10;
            y[z] = 50;
        }
        locate_viagra();
        locate_car();
        locateApple();
        locateHerpes();
        locate_scissors();
        timer = new Timer(DELAY, this);
        timer.start();
     
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        doDrawing(g);
    }
   
    private void doDrawing(Graphics g) {
       
        if (inGame) {

            g.drawImage(viagra, viagra_x, viagra_y, this);
            g.drawImage(car, car_x, car_y, this);
            g.drawImage(apple, apple_x, apple_y, this);
            g.drawImage(herpes, herpes_x, herpes_y, this);
            g.drawImage(scissors, scissors_x, scissors_y, this);
            if(snakeStandart) { for (int z = 0; z < dots+1; z++) {
                if (z == 0) {
                    g.drawImage(head, x[z], y[z], this);
                } else {
                    g.drawImage(ball, x[z], y[z], this);
                }
            }
            }
            if(snakeRed && security >= 6) {
                for (int z = 0; z < dots+1; z++) {
                    if (z == 0) {
                        g.drawImage(red, x[z], y[z], this);
                    } else {
                        g.drawImage(red, x[z], y[z], this);
                    }
                }
               
            }
            if(snakeRed && security < 5) {
                for (int z = 0; z < dots+1; z++) {
                    if (z == 0) {
                        g.drawImage(lightRed, x[z], y[z], this);
                    } else {
                        g.drawImage(lightRed, x[z], y[z], this);
                    }
                }
               
            }
           
           
       
            Toolkit.getDefaultToolkit().sync();

        }
         else {

            gameOver(g);
        }      
    }

    private void gameOver(Graphics g) {
       
        String msg = "Game Over";
        Font small = new Font("Helvetica", Font.BOLD, 14);
        FontMetrics metr = getFontMetrics(small);

        g.setColor(Color.white);
        g.setFont(small);
        g.drawString(msg, (B_WIDTH - metr.stringWidth(msg)) / 2, B_HEIGHT / 2);
       
    }
    private void checkApple() {

        if ((x[0] == apple_x) && (y[0] == apple_y)) {

            dots++;
            locateApple();
     
        }
    }
   
    private void checkHerpes() {
        if(x[0] == herpes_x && y[0] == herpes_y) {
           
             speed_moves = 100;
             timer.setDelay(50);
            locateHerpes();
        }
    }
   
    private void check_scissors() {
        if(x[0] == scissors_x && y[0] == scissors_y) {
            dots = (dots/2);
            locate_scissors();
        }
    }
    private void check_car() {
        if(x[0] == car_x && y[0] == car_y) {
            dots = (dots +3);
            locate_car();
        }
    }
   
    private void check_viagra() {
       
        viagra_counter--;
        if(viagra_counter == 0) {
            viagra_effect = false;
        }
       
        if(x[0] == viagra_x && y[0] == viagra_y) {
            viagra_counter = 4;
            viagra_effect = true;
            locate_viagra();
           
        }
    }

    private void move() {

        for (int z = dots; z > 0; z--) {
            x[z] = x[(z - 1)];
            y[z] = y[(z - 1)];
           
        }

        if (leftDirection) {
            x[0] -= DOT_SIZE;
        }

        if (rightDirection) {
            x[0] += DOT_SIZE;
        }

        if (upDirection) {
            y[0] -= DOT_SIZE;
        }

        if (downDirection) {
            y[0] += DOT_SIZE;
        }
    }

    private void checkCollision() {

        for (int z = dots; z > 0; z--) {

            if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z]) && security == 0) {
                inGame = false;
            }
        }

        if (y[0] >= B_HEIGHT && security == 0) {
            inGame = false;
        }

        if (y[0] < 0 && security == 0) {
            inGame = false;
        }

        if (x[0] >= B_WIDTH && security == 0) {
            inGame = false;
        }

        if (x[0] < 0 && security == 0) {
            inGame = false;
        }
       
        if (!inGame) {
            timer.stop();
        }
       
       
       
        for (int z = dots; z > 0; z--) {

            if ((x[0] == x[z]) && (y[0] == y[z]) && security != 0) {
                security--;
            }
        }

        if (y[0] >= B_HEIGHT && security != 0) {
            security--;
        }

        if (y[0] < 0 && security != 0) {
            security--;
        }

        if (x[0] >= B_WIDTH && security != 0) {
            security--;
        }

        if (x[0] < 0 && security != 0) {
            security--;
        }
       
     
         
       }
   

    private void locateApple() {

        random = (int) (Math.random() * RAND_POS);
        apple_x = ((random * DOT_SIZE));

        random = (int) (Math.random() * RAND_POS);
        apple_y = ((random * DOT_SIZE));
    }

    private void speed_check() {
        if(speed_moves > 0) {
            speed_moves--;
        }
        if(speed_moves == 0) {
            timer.setDelay(300);
        }
       
    }
    private void locateHerpes() {
        random = (int) (Math.random() * RAND_POS);
        herpes_x = ((random * DOT_SIZE));

        random = (int) (Math.random() * RAND_POS);
        herpes_y = ((random * DOT_SIZE));
    }
    private void locate_scissors() {
        random = (int) (Math.random() * RAND_POS);
        scissors_x = ((random * DOT_SIZE));

        random = (int) (Math.random() * RAND_POS);
        scissors_y = ((random * DOT_SIZE));
    }
    private void locate_car(){
        random = (int) (Math.random() * RAND_POS);
        car_x = ((random * DOT_SIZE));

        random = (int) (Math.random() * RAND_POS);
        car_y = ((random * DOT_SIZE));
    }
   
    public void locate_viagra(){
        random = (int) (Math.random() * RAND_POS);
        viagra_x = ((random * DOT_SIZE));

        random = (int) (Math.random() * RAND_POS);
        viagra_y = ((random * DOT_SIZE));
    }
   
    @Override
    public void actionPerformed(ActionEvent e) {
     
        if (inGame) {
           
System.out.println(security);
            check_viagra();
            check_car();
            check_scissors();
            speed_check();
            checkHerpes();
            checkApple();
            checkCollision();
            move();
            show_score();
        }
        repaint();
    }

    private void show_score() {
        score = dots;
        score_panel.setText("size: " + score + "cm");
       
    }
   

    private class TAdapter extends KeyAdapter {

        @Override
        public void keyPressed(KeyEvent e) {

            int key = e.getKeyCode();

            if ((key == KeyEvent.VK_LEFT) && (!rightDirection) && !viagra_effect) {
                leftDirection = true;
                upDirection = false;
                downDirection = false;
            }

            if ((key == KeyEvent.VK_RIGHT) && (!leftDirection) && !viagra_effect) {
                rightDirection = true;
                upDirection = false;
                downDirection = false;
            }

            if ((key == KeyEvent.VK_UP) && (!downDirection) && !viagra_effect) {
                upDirection = true;
                rightDirection = false;
                leftDirection = false;
            }

            if ((key == KeyEvent.VK_DOWN) && (!upDirection) && !viagra_effect) {
                downDirection = true;
                rightDirection = false;
                leftDirection = false;
            }
            if(key == KeyEvent.VK_1) {
                snakeStandart = false;
                snakeRed = true;
                security = 10;
            }
            if(key == KeyEvent.VK_2) {
                 inGame = true;
                 addKeyListener(new TAdapter());
                 dots = 3;

                 for (int z = 0; z < dots+1; z++) {
                     x[z] = 50 - z * 10;
                     y[z] = 50;
                 }
                 setFocusable(true);
                 timer.restart();
                 repaint();
                  locate_viagra();
                     locate_car();
                     locateApple();
                     locateHerpes();
                     locate_scissors();
                 move();
                 repaint();
               
            }
        }
    }
}
 
MoxxiManagarm

MoxxiManagarm

Ich habe ein paar Anmerkungen unabhängig zu deinem Problem, wenn du dies verbesserst ist es vermutlich einfacher dein Problem zu identifizieren:
1. Schön, dass du Code Tags verwendest. Damit bist du schon weitaus besser als viele. Noch schöner wäre es, wenn es Java Code Tags wären [code=java][/code]
2. Im Menü mit dem MoueListener zu arbeiten ist totaler Overkill. Bitte verwende dafür einfach den ActionListener. z.B.
Java:
quit.addActionListener(e -> System.exit(0));
3. Ich empfehle dir das CardLayout um dein Menü und dein Spielpanel übereinanderzulegen. Anstatt zu versuchen es dynamisch zu adden führst du die benötigte View nur noch in den Vordergrund und startest ggf. Prozesse wie die Bewegung der Schlange. Insgesamt will ich darauf hinaus, dass du die ganzen statics entfernen solltest.
4. initUI in der Klasse Frame ist total irritierend. Eigentlich willst du ein neues Spiel starten. Aber du setzt auch die CloseOperation und den Titel in dieser Methode. Der Titel und die Close Operation sind daher auch nicht verfügbar, während du dich noch im Menü befindest.
5. initBoard als extra Methode hat keinen Mehrwert. Wieso nicht direkt im Konstruktor?
6. Ein paar Objekte würden dir gut tun. Apple, Herpes, Scissors, Car - Alle sind letztlich ein Spawnable Objekt, welche Einfluss auf die Schlange haben. Sie haben eine x- und y-Position sowie ein Bild. Du hast zu viele Variablen vom Typ herpes_y und zu viele Methoden vom Typ locateHerpes / checkHerpes, welche durch geeignete Objekte vereinfacht und in der Anzahl reduziert werden könnten. Für uns würde es das deutlich übersichtlicher machen.
7. Außerdem kannst du die Teile der Schlange als Objekt darstellen. z.B. genannt "BodyPart". Meine Empfehlung ist darüber hinaus, dass du diese Bodyparts dann in eine FIFO Datenstruktur packst. Damit lässt sich die Schlange am einfachsten bewegen, du nimmst dann nämlich nur das letzte Teil weg und fügst ein neues vorne entsprechend der Richtung an.
8. Ich sehe spontan keine Spawnabfrage in der Hinsicht, dass aktuell augenscheinlich Apfel, Schwere etc. auf der gleichen Position spawnen können
9. Was macht diese Verzweigung für einen Sinn? Beide Zweige tun genau das Gleiche.
Java:
if (z == 0) {
    g.drawImage(red, x[z], y[z], this);
} else {
    g.drawImage(red, x[z], y[z], this);
}
10. Anstatt den 4 Richtungsvariablen sollte es besser nur 1 sein, welche genau sagt welche die aktuelle Richtung ist.
11. Standart gibt es nicht ;-)
12. Die Variable inGame als solches überflüssig. Du brauchst doch eigentlich nur den Timer zu starten bzw zu stoppen.
 
Zuletzt bearbeitet:
A

Amaisenpär

Ich habe ein paar Anmerkungen unabhängig zu deinem Problem, wenn du dies verbesserst ist es vermutlich einfacher dein Problem zu identifizieren:
1. Schön, dass du Code Tags verwendest. Damit bist du schon weitaus besser als viele. Noch schöner wäre es, wenn es Java Code Tags wären [code=java][/code]
2. Im Menü mit dem MoueListener zu arbeiten ist totaler Overkill. Bitte verwende dafür einfach den ActionListener. z.B.
Java:
quit.addActionListener(e -> System.exit(0));
3. Ich empfehle dir das CardLayout um dein Menü und dein Spielpanel übereinanderzulegen. Anstatt zu versuchen es dynamisch zu adden führst du die benötigte View nur noch in den Vordergrund und startest ggf. Prozesse wie die Bewegung der Schlange. Insgesamt will ich darauf hinaus, dass du die ganzen statics entfernen solltest.
4. initUI in der Klasse Frame ist total irritierend. Eigentlich willst du ein neues Spiel starten. Aber du setzt auch die CloseOperation und den Titel in dieser Methode. Der Titel und die Close Operation sind daher auch nicht verfügbar, während du dich noch im Menü befindest.
5. initBoard als extra Methode hat keinen Mehrwert. Wieso nicht direkt im Konstruktor?
6. Ein paar Objekte würden dir gut tun. Apple, Herpes, Scissors, Car - Alle sind letztlich ein Spawnable Objekt, welche Einfluss auf die Schlange haben. Sie haben eine x- und y-Position sowie ein Bild. Du hast zu viele Variablen vom Typ herpes_y und zu viele Methoden vom Typ locateHerpes / checkHerpes, welche durch geeignete Objekte vereinfacht und in der Anzahl reduziert werden könnten. Für uns würde es das deutlich übersichtlicher machen.
7. Außerdem kannst du die Teile der Schlange als Objekt darstellen. z.B. genannt "BodyPart". Meine Empfehlung ist darüber hinaus, dass du diese Bodyparts dann in eine FIFO Datenstruktur packst. Damit lässt sich die Schlange am einfachsten bewegen, du nimmst dann nämlich nur das letzte Teil weg und fügst ein neues vorne entsprechend der Richtung an.
8. Ich sehe spontan keine Spawnabfrage in der Hinsicht, dass aktuell augenscheinlich Apfel, Schwere etc. auf der gleichen Position spawnen können
9. Was macht diese Verzweigung für einen Sinn? Beide Zweige tun genau das Gleiche.
Java:
if (z == 0) {
    g.drawImage(red, x[z], y[z], this);
} else {
    g.drawImage(red, x[z], y[z], this);
}
10. Anstatt den 4 Richtungsvariablen sollte es besser nur 1 sein, welche genau sagt welche die aktuelle Richtung ist.
11. Standart gibt es nicht ;-)
12. Die Variable inGame als solches überflüssig. Du brauchst doch eigentlich nur den Timer zu starten bzw zu stoppen.
Vielen Dank für deine ausführliche Antwort!

Da ich noch Anfänger bin werde ich mir erstmal Zeit brauchen die einzelnen Punkte zu verstehen und umzusetzen.
Hab selber schon gemerkt, dass das ganze etwas chaotisch ist, wusste nur nicht so genau wie ich es besser ordnen kann, da habe ich jetzt einige gute Anhaltspunkte :). Separate Klassen für die spawnenden Objekte habe ich schon versucht umzusetzen, dann schaue ich mir das genauer an und versuche es nochmal. Danke!
 
MoxxiManagarm

MoxxiManagarm

Hier mal ein kleines Beispiel für das Richtungshandling mit Hilfe eines Enums. Du könntest die aktuelle Richtung als Enum speichern und bei Tastendruck nur noch die Richtung requesten
Java:
public enum Direction {
    UP,
    RIGHT,
    DOWN,
    LEFT;

    public Direction requestDirection (Direction other) {
        if ((this.ordinal() + other.ordinal()) % 2 != 0) {
            return other;
        }

        return this;
    }

    public static void main(String[] args) {
        System.out.println(UP.requestDirection(UP));
        System.out.println(UP.requestDirection(RIGHT));
        System.out.println(UP.requestDirection(LEFT));
        System.out.println(UP.requestDirection(DOWN));

        System.out.println(LEFT.requestDirection(UP));
        System.out.println(LEFT.requestDirection(RIGHT));
        System.out.println(LEFT.requestDirection(LEFT));
        System.out.println(LEFT.requestDirection(DOWN));
    }
}
Ausgabe:
Code:
UP
RIGHT
LEFT
UP
UP
LEFT
LEFT
DOWN
 
Thema: 

JPanel austauschen und Focus geben

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben