arunptl100
arunptl100

Reputation: 15

Java - Changing boolean value in one class from another class

I am currently, for fun, making a pong game however I am currently stuck trying to get the value of my boolean "goingup" to a true state via the w key press. I have the boolean going up in my render class ,as well a int x and int y, and is set to false. In this class i draw a square , with x as int x and y as int y. In another class(Framemake.java) i have a key listener set to my Jframe. In this class i have the keylistener listening for the w key press and release. Here is where my problem arises: If the W key is pressed i want it to change goingup to true and if its released i want it to change going up to false; this works fine but the problem is in my render class i have setup a timer , this is then started in the graphics method (not sure of the proper name). In the timers action performed i have set: if going up is true i want it to print out "going up is true- render". Here is the problem- even though going up is true because of the w key being pressed, the print is not printed onto the screen. (Thankyou for reading this, i needed you to fully understand whats going on- even though it may or may not be really obvious).

Here is the code: Starter.java

public class Starter  {

public static void main(String[] args) {
    Frame frame = new Frame(); 
    frame.Start(); 

}

}

Here is the Frame.java

public class Frame implements Runnable  {
Framemake r = new Framemake();

public void Start(){
    new Thread(this).start();//
}
public void run() {

    try {
        r.framemade();
        }
    catch (Exception e) { //
        e.printStackTrace(); 
    }   

}

    }

Here is parts of Render.java as i was having troubles pasting into this post

public class Render extends JPanel implements ActionListener {

boolean goingup = false;
boolean goingdown = false;
int x = 0; //starting pos of x .
int y = 150;//starting pos of y
Timer tm = new Timer(7, this); //The timer is created



public void paintComponent(Graphics g) {
  Framemake frames = new Framemake();
  super.paintComponent(g);
  tm.start();
  g.setColor(Color.GREEN);
  g.fillRect(x, y, 20, 150);
  g.dispose();
}

public void actionPerformed(ActionEvent e){ //timer
  if(goingup){
    System.out.println("Going up is true- render");
    x++;//for example...
    repaint();
  }
}

Here is Framemake.java

public class Framemake implements KeyListener {
    int WIDTH = 500;
    int HEIGHT = 500;
    Render c = new Render();
    public void framemade() {
        System.out.println("Frame starting");
        //Frame is created here 
        Render render = new Render();
        JFrame frame = new JFrame();
        frame.setSize(WIDTH, HEIGHT);
        frame.setVisible(true);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setTitle("Animation");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Window w = frame;
        w.addKeyListener(this);
        frame.add(render); //displays all graphics from render to the screen
    }
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode == KeyEvent.VK_W) {
            System.out.println("Going up");
            c.goingup = true;
        }
        if (keyCode == KeyEvent.VK_S) {
            System.out.println("Going down");
            c.goingdown = true;
        }
    }
    public void keyReleased(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode == KeyEvent.VK_W) {
            System.out.println("Up terminated");
            c.goingup = false;
        }
        if (keyCode == KeyEvent.VK_S) {
            System.out.println("Down terminated");
            c.goingdown = false;
        }
    }
    public void keyTyped(KeyEvent e) {}
}

I hope the question is clear here (Sorry if I have posted my code incorrectly), any help is appreciated.

Upvotes: 1

Views: 1537

Answers (4)

Nick Louloudakis
Nick Louloudakis

Reputation: 6005

You need to use the observer (or notifier) pattern.

A very simple (and naive) example: Create a class that will play the role of the observable, and an interface with the role of the observer, along with its implementation classes. Hold a list to the observable class of the observer instances to inform when needed, and do it that way

(NOTICE: untested code):

public interface Observer{
  public void notify();
}

public class Observable{
  public List<Observer> _observers;

  public Observable(){
    _observers = new List<Observer>();
  }

  public void registerObserver(Observer obs){
     _observers.add(obs)
  }

  public void unregisterObserver(Observer obs){
    _observers.remove(obs);
  }

  public void notifyObservers{
    for(Observer obs : _observers) { 
       obs.notify();
    }
  }

}

public class SpecificObserver implements Observer{
  //Properties, Ctors etc

  public void notify(){
    //Do stuff when notified here
  }
}


and in your program:

public static void main(string[] args){

  Observable observable             = new Observable();
  SpecificObserver specificObserver = new SpecificObserver();
  //More init code here

  observable.registerObserver(specificObserver);
  //Etc...

  //read input
  string str = YourClass.GetInput();

  while(!str.Equals("EndString"))
  {
    if(str.Equals("SpecificInput"))
    {
      observable.notifyObservers();
    }
    str = YourClass.GetInput();
  }

}

Of course, you can modify it to your needs (add arguments to the Notify method, run the loop to another thread that checks the condition you want rather than the input etc)

Upvotes: 0

Christian Tapia
Christian Tapia

Reputation: 34146

The problem is that in your class Framemake, you are not adding Render c to the frame. You are creating a local variable render instead.

To solve this, just delete the declaration of

Render render = new Render();

and add c to the frame:

frame.add(c);  // Instead of 'frame.add(render)'

Summary: Your method framemade() should look like this:

public void framemade()
{
    System.out.println("Frame starting");
    //Frame is created here 
    JFrame frame = new JFrame();
    frame.setSize(WIDTH, HEIGHT);
    frame.setVisible(true);
    frame.setResizable(false);
    frame.setLocationRelativeTo(null);
    frame.setTitle("Animation");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Window w = frame;
    w.addKeyListener(this);
    frame.add(c); // Change this line
}

Edit:

I would also recommend you to read about why you should use private fields, getters and setters. Try this and this.

Upvotes: 2

Marenthyu
Marenthyu

Reputation: 165

You should be able to do this by simply adding a method like this and then call that: Public void setgoingup (boolean b) { this.goingup = b; }

Ps: i am tired and didn't read all the code - sorry if i missed anything ovious.

Upvotes: 0

Carsten Hoffmann
Carsten Hoffmann

Reputation: 941

I would suppose, that your timer does not fire at all. You should probably start it only once, and not in the paintComponent Method. Since per default it will fire every 7 ms. Also add a line to see if the actionPerformed method actually fires:

public void actionPerformed(ActionEvent e){ //timer
  System.out.println("Timer: actionPerformed");  
  if(goingup){
    System.out.println("Going up is true- render");
    x++;//for example...
    repaint();
  }
}

And why do you call g.dispose(); in the paintComponent method? This method is called on each repaint. This will most likely lead to problems as well.

Upvotes: 0

Related Questions