JFrame不等待JOptionPane执行



我正在做一个项目,在这个项目中我创建了一个简单的乒乓球游戏。如果玩家赢了,我希望弹出一个JOptionPane询问用户是想玩新游戏还是停止游戏。当我添加JOptionPane时,该方法不会等待用户选择按钮,而是继续运行并继续创建JOptionPane,直到它返回堆栈溢出错误。控制它的代码是

int rightMinLeft = Right_Player_Score.getNumber()-Left_Player_Score.getNumber();
boolean rightWon = Right_Player_Score.getNumber() > 20 && rightMinLeft > 1;
if(rightWon)
{
  Object[] options = {"New Game", "Finish"};
  int i = JOptionPane.showOptionDialog(null, "Right Player has won", "Game Over", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
  if(i == 0)
  {
    reset();
  }
  else
  {
    GameOver = true;
  }
}
else if(Left_Player_Score.getNumber() > 20 && Left_Player_Score.getNumber()-Right_Player_Score.getNumber()>1)
{
  Object[] options = {"New Game", "Finish"};
  int i = JOptionPane.showOptionDialog(null, "Right Player has won", "Game Over", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
  if(i == 0)
  {
    reset();
  }
  else
  {
    GameOver = true;
  }
}

有什么建议吗?

编辑:下面是完整的方法:

public void update(Graphics window)
 {
  paint(window);
 }
 public void paint(Graphics window)
 {
   try{
   if(pause)
   {
     Right_Player_Score.draw("Right Player Score", window, 600, 20);
     Left_Player_Score.draw("Left Player Score", window,  0, 20);
     leftPaddle.draw(window);
     rightPaddle.draw(window);
     if(U.LELatch(keys[4]))
     {
       pause = false;
     }
   }
   else
   {
     ball.moveAndDraw(window);
     leftPaddle.draw(window);
     Right_Player_Score.draw("Right Player Score", window, Color.WHITE, 600, 20);
    Left_Player_Score.draw("Left Player Score", window,  Color.WHITE, 0, 20);
    int LeftPaddleBottom = leftPaddle.getY()+(leftPaddle.getHeight());
    int RightPaddleBottom = rightPaddle.getY()+(rightPaddle.getHeight());
    int LeftPaddleTop = leftPaddle.getY();
    int RightPaddleTop = rightPaddle.getY();
    boolean inRangeLeft = ball.getY() > LeftPaddleTop && ball.getY() < LeftPaddleBottom;
    boolean inRangeRight = ball.getY() > RightPaddleTop && ball.getY() < RightPaddleBottom;
    if(ball.getX()<=10)
    {
     ball.setXSpeed(-ball.getXSpeed());
     Right_Player_Score.increment();
    }
    else if(ball.getX()>=790)
    {
      ball.setXSpeed(-ball.getXSpeed());
      Left_Player_Score.increment();
    }
    else if((inRangeLeft && ball.getX()<=leftPaddle.getX()+leftPaddle.getWidth()))
    {
      ball.setXSpeed(-ball.getXSpeed());
      numTimes ++;
    }
    else if(inRangeRight && ball.getX()>=rightPaddle.getX())
    {
      ball.setXSpeed(-ball.getXSpeed());
      numTimes ++;
    }
    if(!(ball.getY()>=10 && ball.getY()<=450))
    {
     ball.setYSpeed(-ball.getYSpeed());
    }
    if(keys[0] == true)
    {
     leftPaddle.moveUpAndDraw(window);
    }
    else if(keys[1] == true)
    {
     leftPaddle.moveDownAndDraw(window);
    }
    else
    {
      leftPaddle.draw(window);
    }
    if(keys[2] == true)
    {
      rightPaddle.moveUpAndDraw(window);
    }
    else if(keys[3] == true)
    {
      rightPaddle.moveDownAndDraw(window);
    }
    else
    {
      rightPaddle.draw(window);
    }
    int rightMinLeft = Right_Player_Score.getNumber()-Left_Player_Score.getNumber();
    boolean rightWon = Right_Player_Score.getNumber() > 20 && rightMinLeft > 1;
    if(rightWon)
    {
      Object[] options = {"New Game", "Finish"};
      int i = JOptionPane.showOptionDialog(frame, "Right Player has won", "Game Over", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
      //window.setColor(Color.BLACK);
      //window.drawString("Right Player has won",200,400);
      //Thread.currentThread().sleep(2000);
      //int i = 1;
      if(i == 0)
      {
        reset();
      }
      else
      {
        GameOver = true;
      }
    }
    else if(Left_Player_Score.getNumber() > 20 && Left_Player_Score.getNumber()-Right_Player_Score.getNumber()>1)
    {
      Object[] options = {"New Game", "Finish"};
      int i = JOptionPane.showOptionDialog(frame, "Left Player has won", "Game Over", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
      //window.setColor(Color.BLACK);
      //window.drawString("Left Player has won",200,400);
      //Thread.currentThread().sleep(2000);
      //int i = 1;
      if(i == 0)
      {
        reset();
      }
      else
      {
        GameOver = true;
      }
    }
    Right_Player_Score.draw("Right Player Score", window, 600, 20);
    Left_Player_Score.draw("Left Player Score", window, 0, 20);
    if(numTimes == 10)
    {
      numTimes = 0;
      if(ball.getXSpeed() == Math.abs(ball.getXSpeed()))
      {
        ball.setXSpeed(ball.getXSpeed() + 1);
      }
      else
      {
        ball.setXSpeed(ball.getXSpeed() - 1);
      }
      if(ball.getXSpeed()>MAXSPEED)
      {
        ball.setXSpeed(MAXSPEED);
      }
    }
    pause = U.LELatch(keys[4]);
   }
   }
   catch(Exception e)
   {
   }
 }

这是用在"公共类GUI_Controller extends Canvas implements KeyListener, Runnable"

注意:注释部分是让用户至少看到一些东西的权宜之计。

您看到的行为是因为您重载了paint(Graphics g)方法。

来自paint(Graphics g) JavaDoc

该方法在需要绘制组件内容时调用;这样的当组件第一次被展示或损坏和需要时修复。

在您的情况下,可能发生的情况是对JOptionPane.showOptionDialog()的调用导致JDialog显示在您的Canvas之上,从而触发对paint()的另一个调用。这反过来导致另一个调用JOptionPane.showOptionDialog()触发另一个调用paint(),等等…这将继续,直到您得到StackOverflowErrorOutOfMemoryError

在实践中,paint()被频繁调用,所以它应该是非常有效的。通常只有您的自定义绘图应该在paint()方法中完成。

其他逻辑应该存在于不同的方法中。您应该将评分和用户交互的逻辑移到paint()方法之外,只保留绘图。

Edit: 在没有看到更多代码的情况下,我不能给你一个具体的建议,告诉你在哪里移动与绘画不直接相关的逻辑。您可能会发现,回顾一下Java Swing教程中关于执行自定义绘画的部分会有所帮助。

JOptionPane作为您当前帧的第一个参数而不是null可能会有所帮助。

最新更新