如果调用theView.continueToGame()
,为什么屏幕不会使用新面板(由cont()
调用)更新?如果我评论ask()
调用cont()
的位置,它似乎有效。有人可以解释为什么会这样吗?似乎循环中的东西搞砸了。
Driver.java
public class Driver {
public static void main(String[] args)
{
Controller con = new Controller();
con.ask();
}
}
Controller.java
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();
}
}
View.java
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);
}
}
无论是
还是答案 0 :(得分:2)
您遇到了一个线程问题,阻塞方法会阻止您的GUI事件线程冻结您的程序。这是因为您正在尝试将控制台程序与其线性程序逻辑与事件驱动的GUI程序相结合。
解决方案很简单:不要这样做。摆脱你的new Scanner(System.in)
,只能通过GUI以事件驱动的方式获取用户输入。您可以使用JOptionPane或JDialog来获取此输入,要么效果很好,要么不是new Scanner(System.in)
。我自己,我只是使用JOptionPane.showConfirmDialog(...)
。
作为旁注,您正在使用类名称,例如View和Controller,就像您计划进行模型 - 视图 - 控制类型的程序设计一样, GREAT < / strong>想法,如果你问我,但是控件应该处理GUI的用户输入,而不是控制台。
修改强>
我错了 - 你的问题是你在交换组件后没有在容器上调用revalidate()
和repaint()
。即,
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 {
}