Несколько панелей / холст - PullRequest
0 голосов
/ 12 апреля 2020

Я ищу способ динамического переключения между панелями / между панелью или холстом. Подробнее c: Я занимаюсь разработкой игры. В моем коде есть класс, который расширяет canvas и реализует Runnable, а в конструкторе Game он создает новый экземпляр класса с именем window. Это класс окна:

public class Window extends Canvas {
private static final long serialVersionUID = -299686449326748512L;

public static JFrame frame = new JFrame();

public Window(int width, int height, String title, Game game) {
   // JFrame frame = new JFrame();
    frame.setPreferredSize(new Dimension(width, height));
    frame.setMaximumSize(new Dimension(width, height));
    frame.setMinimumSize(new Dimension(width, height));
    frame.setTitle(title);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setResizable(false);
    frame.setLocationRelativeTo(null);
    frame.add(game);
    frame.setVisible(true);
    game.start();
 }
}

Я хочу иметь возможность удалить игру из фрейма, активировать другую панель и остановить выполнение Game. Я уже пробовал:

game.stop();
Window.frame.remove(game);

, но это делает программу к sh. Это методы start () и stop ():

/**
 * starts the game.
 */
public synchronized void start() {
    thread = new Thread(this);
    thread.start();
    running = true;
}
 /**
 * tries to stop the game.
 */
public synchronized void stop() {
    try {
        thread.join();
        running = false;
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Моя главная цель - иметь возможность сыграть ролик, если произошло какое-то событие, и я пытаюсь использовать для этой цели vlcj. Если у кого-то есть идея, которая позволит мне достичь этой цели, это тоже было бы здорово.

1 Ответ

0 голосов
/ 13 апреля 2020

Я сделал пример, делая то, что я думаю, что вы хотите без макета карты, и используя поток. Я думаю, что это подтверждение концепции, что то, что вы просите, возможно. Ниже я приведу несколько вещей, которые я бы сделал, чтобы улучшить его.

import javax.swing.*;
import java.awt.*;
public class SwapCards{
    Thread gameLoop;
    volatile boolean running = false;
    double x = 0;
    double y = 0;
    double theta = 0;
    JFrame frame = new JFrame("swapped");        
    Canvas gamePanel = new Canvas(){
        public void paint(Graphics g){
            super.paint(g);
            g.setColor(Color.BLACK);
            g.drawOval((int)x, (int)y, 25, 25);
        }
    };
    Canvas nonGame = new Canvas(){
        public void paint(Graphics g){
            super.paint(g);
            g.setColor(Color.BLUE);
            g.fillRect(0,0,200, 200);
        }
    };
    public void step(){
        x = 100 + 50*Math.sin( theta );
        y = 100 + 50*Math.cos( theta );
        theta += 0.02;
        if(theta > 6.28) theta = 0;
    }

    public void startGameLoop(){
        frame.remove(nonGame);
        frame.add(gamePanel, BorderLayout.CENTER);
        frame.validate();
        running = true;
        gameLoop = new Thread(()->{
            while(running){
                step();
                gamePanel.repaint();
                try{
                    Thread.sleep(30);
                }catch (Exception e){
                    running = false;
                    throw new RuntimeException(e);
                }
            }
        });
        gameLoop.start();
    }
    public void stopGameLoop(){
        frame.remove(gamePanel);
        frame.add(nonGame, BorderLayout.CENTER);
        running = false;
        try{
            gameLoop.join();
        } catch(Exception e){
            throw new RuntimeException(e);
        }
    }
    public void buildGui(){
        JButton button = new JButton("action");
        button.addActionListener( evt->{
           if(!running){
               startGameLoop();
           } else{
               stopGameLoop();
           }
        });
        frame.add(nonGame, BorderLayout.CENTER);
        frame.add(button, BorderLayout.SOUTH);
        frame.setSize(400, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

    }
    public static void main(String[] args){
        EventQueue.invokeLater( new SwapCards()::buildGui );
    }
}

Прежде всего, Canvas несколько устарел, используйте JPane и переопределите paintComponent. Это дает вам больше доступа к силе свинга.

В этом примере я выполняю тривиальную работу, поэтому нить абсолютно избыточна, я могу заменить ее на javax.swing.Timer.

    Timer timer = new Timer(30, evt->{
       step(); 
       gamePanel.repaint();
    });

Затем в методах start и stop я просто вызываю timer.start() или timer.stop() соответственно.

Использование CardLayout делает немного более понятным, что вы хотите сделать, плюс в нем есть методы для навигации по картам. Например. Если у вас есть вырезанная сцена с серией компонентов, которые вы хотите показать, вы можете использовать cardLayout.next(parent).

. При создании макета:

cards = new CardLayout();
swap = new JPanel(cards);
swap.add(gamePanel, "game");
swap.add(nonGame, "nogame");
cards.last(swap);
frame.add(swap, BorderLayout.CENTER);

Это добавит карты к swap и заставь его показать "nogame". Затем в методах start / stop мы просто переключаемся на соответствующую карту.

cards.show(swap, "game");
...