有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

调用Scanner后,java方法不会更新GUI

如果调用了cont(),为什么屏幕不更新为新面板(称为theView.continueToGame())?如果我注释掉ask()调用cont()的地方,这似乎是可行的。有人能解释一下为什么会这样吗?看来有什么东西把循环搞砸了

司机。爪哇

public class Driver {

    public static void main(String[] args)
    {
        Controller con = new Controller();
        con.ask();
    }

}

控制器。爪哇

public class Controller {

    private View theView = new View();
    private Model theModel = new Model();

    public void ask()
    {
        theView.displayMenu();

        cont();

        System.out.println("ready");

        theView.continueToGame();


    }

    private void cont()
    {
        Scanner stdin = new Scanner(System.in);

        int input = 0;

        while(!(input == 1))
        {
            System.out.println("Enter 1 to continue");
            input = 0;
            try 
            {
                input = stdin.nextInt();
            } 
            catch (InputMismatchException e) 
            {
                System.out.println("error");
                stdin.next();
            }

        }

        stdin.close();
    }
}

视图。爪哇

public class View extends JFrame {

    /**
     * Serial id
     */
    private static final long serialVersionUID = 1L;

    private String String1 = "1";
    private String String2 = "2";

    View()
    {
        setVisible(true);
        setTitle("Tic-Tac-Toe");
        setSize(400,400);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    public void displayMenu()
    {
        this.add(new startMenu());
    }

    public void continueToGame()
    {
        this.getContentPane().removeAll();
        this.add(new gameScreen());
    }

    class startMenu extends JPanel{

        /**
         * Serial id
         */
        private static final long serialVersionUID = 1L;

        private startMenu()
        {
            setVisible(true);
        }

        public void paintComponent(Graphics g)
        {
            super.paintComponent(g);
            setBackground(Color.blue);

            g.setColor(Color.black);
            g.drawString(String1, this.getWidth()/2, this.getHeight()/2);
        }

    }

    class gameScreen extends JPanel
    {

        /**
         * Serial id
         */
        private static final long serialVersionUID = 1L;

        private gameScreen()
        {
            setVisible(true);
        }

        public void paintComponent(Graphics g)
        {
            super.paintComponent(g);
            setBackground(Color.green);

            g.setColor(Color.black);

            g.drawString(String2, this.getWidth()/2, this.getHeight()/2);
        }

    }



}

编辑:

cont()更改为

private void cont()
{
    Integer input = -1;

    while(!(input == 0))
    {

        input = JOptionPane.showConfirmDialog(theView, "Continue?", null, JOptionPane.YES_OPTION);
        System.out.println(input);
    }


}

也不行


共 (1) 个答案

  1. # 1 楼答案

    您遇到了一个线程问题,其中一个阻塞方法正在阻止GUI的事件线程冻结程序。这是因为您试图将控制台程序及其线性程序逻辑与事件驱动GUI程序结合起来

    解决办法很简单:不要这样做。摆脱new Scanner(System.in),只通过GUI以事件驱动的方式获取用户输入。您可以使用JOptionPane或JDialog来获取此输入,这两种方法都很有效,但是new Scanner(System.in)却不行。我自己,我只会使用JOptionPane.showConfirmDialog(...)

    作为旁注,您使用的类名,如视图和控制器,就好像您计划进行一个模型-视图-控件类型的程序设计,如果您问我,这是一个非常好的想法,但是控件应该处理GUI的用户输入,而不是控制台的输入


    编辑
    我错了。您的问题是,在交换组件后,您没有在容器上调用revalidate()repaint()。i、 e

    public void continueToGame()  {
        this.getContentPane().removeAll();
        this.add(new gameScreen());
        revalidate(); // tells layout managers to layout new components
        repaint();  // redraw everything
    }
    

    最好不要担心这些事情,使用CardLayout交换您的视图JPanel


    编辑2
    CardLayout实际上非常易于使用,但如果将其添加到JFrame,实际上就是将其添加到contentPane,并且在调用CardLayout对象的show方法时必须使用contentPane。例如:

    import java.awt.CardLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import javax.swing.*;
    
    public class Driver {
    
       public static void main(String[] args) {
          Controller con = new Controller();
          con.ask();
       }
    }
    
    class Controller {
    
       private View theView = new View();
       private Model theModel = new Model();
    
       public void ask() {
          theView.displayMenu();
    
          if (cont(theView)) {
             System.out.println("ready");
             theView.setView(View.GAME);
          }
       }
    
       private boolean cont(View theView) {
          int result = JOptionPane.showConfirmDialog(theView, "Go on to game?");
          return result == JOptionPane.YES_OPTION;
       }
    }
    
    class View extends JFrame {
    
       private static final long serialVersionUID = 1L;
       public static final String START = "start";
       public static final String GAME = "game";
       private String String1 = "1";
       private String String2 = "2";
       private CardLayout cardLayout = new CardLayout();
    
       View() {
          // setVisible(true); // don't call this til all added to gui
          setTitle("Tic-Tac-Toe");
          // setSize(400, 400); 
          setDefaultCloseOperation(EXIT_ON_CLOSE);
    
          getContentPane().setLayout(cardLayout);
          add(new StartMenu(), START);
          add(new GameScreen(), GAME);
    
          pack();
          setVisible(true);
       }
    
       public void displayMenu() {
          this.add(new StartMenu());
       }
    
       public void setView(String constant) {
          cardLayout.show(getContentPane(), constant);
       }
    
       // class names should begin with an upper case letter
       class StartMenu extends JPanel {
          private static final int PREF_W = 400;
          private static final int PREF_H = PREF_W;
    
          private static final long serialVersionUID = 1L;
    
          private StartMenu() {
             setVisible(true);
          }
    
          @Override
          public Dimension getPreferredSize() {
             return new Dimension(PREF_W, PREF_H);
          }
    
          public void paintComponent(Graphics g) {
             super.paintComponent(g);
             setBackground(Color.blue);
    
             g.setColor(Color.black);
             g.drawString(String1, this.getWidth() / 2, this.getHeight() / 2);
          }
    
       }
    
       // class names should begin with an upper case letter
       class GameScreen extends JPanel {
    
          private static final long serialVersionUID = 1L;
    
          private GameScreen() {
             setVisible(true);
          }
    
          public void paintComponent(Graphics g) {
             super.paintComponent(g);
             setBackground(Color.green);
             g.setColor(Color.black);
             g.drawString(String2, this.getWidth() / 2, this.getHeight() / 2);
          }
    
       }
    }
    
    class Model {
    
    }