0

I'm stuck with my school work in Java, where I'm building a TicTacToe game, using the MVC design pattern. I have three classes (Model, View, Controller) and I'm at the last step from having a final product. The problem IS:

My JTextFields WON'T keep their value that the user enters. What I'm trying to get is that the names chosen by the user will be stored and able to retrive through the controller back to the model. I've tried different methods, asked people for help and searched several forums.

I'm using the Observable interface together with these classes and have ActionEvent in controller.

Please, take a look and let me know what you think!

OBS! As you will se, I've tried several different ways to fix this, that's why the code looks like s*it....

/*View Class */
import java.awt.*;

import java.awt.image.BufferedImage;
import java.io.*;
import java.text.ParseException;
import java.util.*;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.Border;


public class View extends JFrame implements Observer{

private JLabel _titleLabel, _westLabel, _eastLabel, _southLabel, _centerLabel;
private JPanel titlePanel, eastPanel, westPanel, southPanel, centerPanel, center2Panel, south2Panel;
private BufferedImage[] images;
private JButton _startButton;
private Model _model;
private Controller _controller;
public JTextField _player1, _player2;
private JButton[] button = new JButton[9];
private String path;
public String _player1Name, _player2Name;

// The title window (NORTH)




public View(Model aModel, Controller aController) {

    _model = aModel;
    _controller = aController;

    for (int i = 0 ; i<9; i++)
        button[i] = new JButton();


    // pre for path: Requires that pictures are in the same map as the core folder.

    path = "./";

    // Creating the main background for the game.

    this.setContentPane(new JLabel (new ImageIcon(path + "GameFrame.png")));
    this.setLayout(new BorderLayout());

    // Adding all the initiated panels for the main BorderLayout.       

    this.add(titlePanel, BorderLayout.NORTH);
    this.add(westPanel, BorderLayout.WEST);
    this.add(eastPanel, BorderLayout.EAST);
    this.add(southPanel, BorderLayout.SOUTH);
    this.add(centerPanel, BorderLayout.CENTER);

    // Setup for the main frame/game.           

    this.setTitle("Tic Tac Toe Game");
    this.setSize(600,600);
    this.setVisible(true);
    this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    this.setResizable(false);

}


public void update(Observable aModel, Object arg) {


    if (_model.getStart()) {

        enterName();


    if (_model.getGameStart()) {
        System.out.println("Booting up");


        System.out.println(getField1() + getField2());

        _controller.setNames(getField1(), getField2());



    }


    }

}



public void enterName(){

    //A form to enter the names of the players

    centerPanel.remove(center2Panel);
    validate();
    center2Panel = new JPanel ();
    centerPanel.add(center2Panel);
    center2Panel.setOpaque(false);

    // Copied code, works the same way and keeps the same pattern.

    center2Panel.setLayout(new GridBagLayout ());
    GridBagConstraints c = new GridBagConstraints();

    c.fill = GridBagConstraints.HORIZONTAL;
    c.insets = new Insets(1, 1, 1, 1);
    c.gridwidth = GridBagConstraints.REMAINDER;

    center2Panel.add(new JLabel("First enter your names: "), c);

     _player1 = new JTextField("Skriv namn");
    _player1.setColumns(20);




    _player2 = new JTextField(_model.getPlayerName(2));
    _player2.setColumns(20);

    //_player2.setText(getField1());


    center2Panel.add(_player1, c);
    center2Panel.add(_player2, c);

    _startButton = new JButton ("Start Game");
    center2Panel.add(_startButton, c);
    _startButton.addActionListener(_controller);
    _startButton.setActionCommand("start_button");



    validate(); 

    _player1Name = _player1.getText();
}

public String getField1(){


    System.out.println(_player1Name);
    return _player1.getText();
}
public String getField2(){
    return _player2.getText();
}

}

/* Controller class */
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import javax.swing.event.MouseInputAdapter;


 public class Controller extends MouseInputAdapter implements ActionListener{

Model _model;
public Controller(Model amodel) {

    _model = amodel;

}


public void setNames (String One, String Two) {

    System.out.println(One+Two);

    _model.setPlayerNames(One, Two);

}


public void actionPerformed(ActionEvent e) {

        if (e.getActionCommand().equals("start")){

        _model.isStart();

        }




        if (e.getActionCommand().equals("start_button")){
            System.out.println("startbutton");

            _model.namesEntred();
            _model.isGameStart();
        }


        if (e.getActionCommand().equals("exit")){

            System.exit(0);

        }
    }   
}


   /* Model Class */

    import java.util.Observable;

    import javax.swing.DefaultListModel;
    import javax.swing.JOptionPane;

    public class Model extends Observable {

private String _player1Name, _player2Name;
private int _player1Score, _player2Score, _player = 1, _turns;
private String[] _gridList;
private boolean _namesEntered;
private boolean _tie, _win, _victory, _start, _startButton;
private View _view;

public Model(){

    _namesEntered = false;
    _gridList = new String[9];
    _player1Name = "Player1";
    _player2Name = "Player2";
    _tie = false;
    _win = false;
    _victory = false;
    _start = false;
    _startButton = false;
}

public String getPlayerName(int player){

    if(player == 1)
        return _player1Name;
    else
        return _player2Name;
}



public void setPlayerNames(String One, String Two) {


    _player1Name = One; 
    _player2Name = Two;




    System.out.println(_player1Name + _player2Name);
}





public void newTurn(){

    _turns  = _turns + 1;

    if(_player == 1)
        _player = 2;
    else 
        _player = 1;

}

public int getTurn(){

    return _player;

}

public String getPlayer () {

    if (_player == 1) {
    return _player1Name;

}
    else {
        return _player2Name;
    }
}

public String getGridBrick(int i){

    return _gridList[i];


}


public static void main(String[] args) {

    Model _model = new Model();
    Controller _controller = new Controller(_model);
    View _view = new View(_model, _controller);

    _model.addObserver(_view);
}



public void isStart () {

    _start = true;

    this.setChanged();
    this.notifyObservers();
    System.out.println("isStart");
}

public boolean getStart () {

    System.out.println("getStart");
    return _start;

}

public void isGameStart () {

    _startButton = true;

    this.setChanged();
    this.notifyObservers();

}

public boolean getGameStart () {

    return _startButton;

}

public void namesEntred() {

    _namesEntered = true;

    this.setChanged();
    this.notifyObservers();
}

public boolean getNames () {

    return _namesEntered;

}

}

Jack
  • 11
  • 5
  • 2
    1) For better help sooner, post an [SSCCE](http://sscce.org/). 2) What is your question? – Andrew Thompson Apr 16 '13 at 12:01
  • 1
    _View Class (relevant methods)_ How do you know that the rest is not relevant? Anyway, it's pretty much impossible to tell what the problem is without a complete code. We have no idea of what the rest of the code is. What I can tell you is that `_player1.setText(_player1.getText());` is useless. `paintBoard(); paintScore();` looks very suspicious (usually, all you do is calling `repaint()`. You should rather use `revalidate()` over `validate()`. `centerPanel.remove(center2Panel); validate(); center2Panel = new JPanel();` looks suspicious too. – Guillaume Polet Apr 16 '13 at 12:09
  • 1: Well, is there any simple way to post the complete code here? Creating a SSCCE feels hard, most of the code is needed (I'm rookie). My question is: Shouldn't the TextFields text be stored and return if I call the getField() method? – Jack Apr 16 '13 at 12:40
  • 1
    @Jack Creating an [SSCCE](http://sscce.org) is actually not that hard and I would say that half of the time, the simple process of trying to create one leads you to finding the problem. Now I see one huge issue in your code: in the method `enterName()`, you declare 2 local variables `JTextField _player1` and `JTextField _player2` which hide the class members with the same name. I am pretty sure that you should simply write `_player1 = new JTextField...` and `_player2 = new JTextField...` instead. That might be the root of your issue. – Guillaume Polet Apr 16 '13 at 12:46
  • @GuillaumePolet I've made some kind of SSCCE, just for the code to be seen. It wont work to compile and run it, but the problem isn't the running, it's still to retrive the value from the user input on a JTextField. It needs to go through Controller -> Model and then change the View (MVC) – Jack Apr 16 '13 at 13:44
  • @Jack Have you fixed the issues of the local variables that are shadowing the class members? If not, start there, because I am pretty sure it is part of your problem, if not your only problem. – Guillaume Polet Apr 16 '13 at 13:49
  • @GuillaumePolet Where do you mean? Observers? – Jack Apr 16 '13 at 13:54
  • @Jack SSCCE: strip everything unnecessary down, keep only one field to exemplify the issue, etc, but make it compilable and runnable – t0r0X Apr 16 '13 at 15:45
  • For reference, you might compare your implementation with this [working example](http://stackoverflow.com/a/3072979/230513). – trashgod Apr 16 '13 at 17:34
  • *"..some kind of SSCCE.."* Stop kidding yourself. There is only ***one*** kind of SSCCE. Everything else is ***not** an SSCCE.* – Andrew Thompson Apr 17 '13 at 03:13

2 Answers2

1

your code is really long and it is pretty hard to analyze it...

But I think I can give some conception tips...

you can change its architecture to something like this one

not tested

class View extends ... implements ...
{
  private Controller controller =new Controller(this);

  View(){...}

  protected JTextField getTextField0(){return this.jTextField0;}
  protected JTextField getTextField1(){return this.jTextField1;}
}

class Controller implements ... 
{

  private Model model=new Model();

  private View view;
  protected Controller(View view){this.view=view;}

  protected void setNames()
  {
    this.getModel().setNames(this.getView().getTextField0().getText(),this.getView().getTextField1().getText())
  }


  private Model getModel(){return this.model;}
  private View getView(){return this.view;}
}

class Model implements ...
{
  ...

  protected void setNames(String one,String two){...}
}

P.S. I write the code as a basic conception so you have to adapt it for your case

I hope it will help you

0

Found the problem on this one. It was a major fail from my side.

  • When a new view was made, the old one was thrown away, thich also threw away the "text" i was trying to reach.

Problem solved when getText was made before throwing the view away!...

Jack
  • 11
  • 5