Swing GUI зависает при использовании потоков - PullRequest
1 голос
/ 14 мая 2019

Я пишу игру с прорывом, и все работает нормально, кроме одной мелочи.

У меня есть объект ball, который выходит из потока и RepainterThread, который может реализовывать Runnable или расширяет Thread, который вызывает метод рисования, которыйперерисовывает игровое поле с кирпичами, веслом и мячомдолжно быть приостановлено или нет.

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

Затем я приостанавливаю игру с помощью кнопки, для которой я установил Актив на ложь.Мяч останавливается как надо.Затем я нажимаю кнопку продолжения, и isActive снова становится верным.Объект ball снова начинает работать, и метод запуска Repainter Thread также запускается, но Swing Frame полностью зависает.

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

Я потратил на это дни, пожалуйста, помогите

public class Ball extends MovingObject {

    private double hSpeed; // Horizontal velocity
    private double vSpeed; // Vertical velocity

    public Ball() {
        this.color = Color.MAGENTA;
        this.height = GameSettings.ballSize;
        this.width = GameSettings.ballSize;
        this.position = new Point2D.Double(GameSettings.defaultBallX, GameSettings.defaultBallY);
        this.hSpeed = GameSettings.ballHSpeed;
        this.vSpeed = GameSettings.ballYSpeed;
    }

    public Ball(Ball ball) {
        color = ball.color;
        height = ball.height;
        width = ball.width;
        position = ball.position;
        hSpeed = ball.hSpeed;
        vSpeed = ball.vSpeed;
    }

    public double getHSpeed() {
        return this.hSpeed;
    }

    public double getVSpeed() {
        return this.vSpeed;
    }


    public void run() {

        try {
            while (GameController.getInstance().getGameState().isActive()) {
                System.out.println("Ich run im Ball");
                Thread.sleep(10);
                this.meetingWall();
                this.meetingBrick();
                this.position.setLocation(this.getPosition().getX() + this.hSpeed,
                        this.getPosition().getY() + this.vSpeed);
                if (this.meetingPaddle()) {
                    this.newDirection();
                }
                if (this.out()) {
                    GameController.getInstance().stopGame();
                    this.stopThread();
                }

                this.position = this.getPosition();

            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    public void stopThread() {
        GameController.getInstance().getGameState().setActive(false);
    }

    public void startThreadAgain() {
        this.run();
    }

    @Override
    public synchronized void start() {
        this.position.setLocation(GameSettings.defaultBallX, GameSettings.defaultBallY);
        super.start();
    }


    class GamePanel extends JPanel {
        private static final long serialVersionUID = 1L;
        private final Color backgroundColor = Color.BLACK;
        GameState gameState = GameController.getInstance().getGameState();

        public GamePanel() {
            super();

            this.addKeyListener(new KeyListener() {
                // Dieser KeyListener soll auf Inputs der Pfeiltasten nach links
                // <- und rechts -> hoeren und eine entsprechende Bewegung des
                // Schlaegers erwirken, aber nur, wenn das Spiel nicht
                // pausiert/gestoppt ist.
                public void keyPressed(KeyEvent keyEvent) {
                    if (gameState.isActive()) {// gameState.isActive()
                        if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) {
                            gameState.getPaddle().setPositionRigth();
                        }

                        if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT) {
                            gameState.getPaddle().setPositionLeft();
                        }
                    }

                }

                public void keyReleased(KeyEvent keyEvent) {
                    // TODO
                }

                public void keyTyped(KeyEvent arg0) {
                }
            });
        }


        public void paint(Graphics g) {
            Graphics2D graphics2D = (Graphics2D) g;
            graphics2D.setColor(this.backgroundColor);
            graphics2D.fillRect(0, 0, this.getWidth(), this.getHeight());

            for (int i = 0; i < gameState.getBricks().length; i++) {
                for (int j = 0; j < gameState.getBricks()[i].length; j++) {
                    if ((gameState.getBricks()[i][j] != null)) {
                        graphics2D.setColor(gameState.getBricks()[i][j].getColor());

                        graphics2D.fillRect(
                                (i * GameSettings.brickWidth) + (i + 1) * (GameSettings.spaceAroundBrick + 1),
                                (j * GameSettings.brickHeight) + (j + 1) * GameSettings.spaceAroundBrick,
                                GameSettings.brickWidth, GameSettings.brickHeight);
                    }
                    scoreLabel.setText(this.gameState.getScore() + "");

                    gameState.getPaddle().draw(graphics2D);
                    gameState.getBall().draw(graphics2D);
                }
            }

        }
    }


// First Approach


    private class RepainterThread implements Runnable {

        public RepainterThread() {
            System.out.println("RepainThreadCOntructor");
        }

        private void updateGUI() {
            System.out.println("before invoke later");

            System.out.println("repaint");
            getGamePanel().requestFocus();
            getGamePanel().repaint();

        }

        @Override
        public void run() {
            System.out.println("Repainter run");
            System.out.println(GameController.getInstance().getGameState().isActive());

            while (GameController.getInstance().getGameState().isActive()) {
                System.out.println("inside while");
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                updateGUI();

            }

        }

    }

// Second Approach

        private class RepainterThread implements Runnable {


            public RepainterThread() {
                System.out.println("RepainThreadCOntructor");
            }

            private void updateGUI(){

                SwingUtilities.invokeLater(new Runnable() {         
                    public void run() {
                        System.out.println("repaint");
                        getGamePanel().requestFocus();
                        getGamePanel().repaint();
                    }
                });

            }
            @Override
            public void run() {
                System.out.println("Repainter run");
    System.out.println(GameController.getInstance().getGameState().isActive());

                    while (GameController.getInstance().getGameState().isActive()) {
                        System.out.println("inside while");
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }

                        updateGUI();


                    }

            }

        }

Рамка больше не должна зависать

, пожалуйста, помогите

1 Ответ

1 голос
/ 14 мая 2019

Это довольно дикое предположение, но, поскольку, согласно вашему описанию, программа работает правильно, пока вы не приостановите и не приостановите ее, проблема, скорее всего, связана с методом startThreadAgain:

public void startThreadAgain() {
    this.run();
}

Ваш кодне показывает, как вы вызываете этот метод, но в этот метод вы просто вызываете this.run(), т.е. вы вызываете метод run как обычный блокирующий метод, хотя, вероятно, все еще в потоке пользовательского интерфейса.Вместо этого вы должны вызвать start(), чтобы запустить новый поток, выполняющий метод run.

public void startThreadAgain() {
    super.start(); // not this start, otherwise it resets the ball's location
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...