-2

Suppose you have class A and class B. Class A is the main class which builds a frame with a GUI. It contains all the GUI variables (such as buttons, labels, strings) along with whatever methods that you'll be using. Class A also creates a class B object:

ClassB name = new ClassB();

Inside class B you will find a for loop. Now, once the for loop is finished looping, I want to call a method located in class A. Whenever I try calling a method located in class A, Eclipse suggests making that method static. I'm trying to avoid making static methods. Is there a way of calling class A's methods from class B without making anything static?

Class A:

public class Game extends JFrame implements ActionListener {

// init variables
private JPanel contentPane;
private JPanel panel_actions;
private JButton btn_strike;
private JProgressBar progBar_loading;

private Load load;

// create the frame
public dsgsd() {

    load = new Load();

    // frame initializing
    setResizable(false);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
    setBounds(100, 100, 890, 480);
    setTitle("BeyondInfinity - Group Project for CS1100");
    getContentPane().setLayout(null);
    setVisible(true);

    // create a root panel
    contentPane = new JPanel();
    contentPane.setLayout(null);
    contentPane.setBounds(0, 0, 884, 451);
    contentPane.setVisible(true);
    getContentPane().add(contentPane);

    // create actions panel for displaying attack buttons
    panel_actions = new JPanel();
    panel_actions.setBorder(new EmptyBorder(10, 10, 10, 10));
    panel_actions.setBounds(10, 306, 854, 68);
    panel_actions.setBackground(new Color(100, 149, 237));
    panel_actions.setLayout(new GridLayout(0, 6, 10, 0));
    panel_actions.setVisible(true);
    contentPane.add(panel_actions);

    // create attack button #1
    btn_strike = new JButton("Strike");
    btn_strike.setFocusable(false);
    btn_strike.setVisible(true);
    btn_strike.addActionListener(this);
    panel_actions.add(btn_strike);

}

// create action listener
public void actionPerformed(ActionEvent evt) {

    if (evt.getSource().equals(btn_strike)) {
        load.start();
    }
}

public void executeTasks() {
    //TODO do something 
}

// set value for the loading bar
public void setProgBar_loading(int val) {
    progBar_loading.setValue(val);
    progBar_loading.repaint();
}


}

Class B:

public class Load {
  private Timer timer;
  private int i;

  public void start() {
    // reset loading bar
    Game.setProgBar_loading(0);
    i = 0;

    ActionListener listener = new ActionListener() {
        public void actionPerformed(ActionEvent e) {

            if (i > 100) {
                timer.stop();
                Game..executeTasks();
            } else
                Game.setProgBar_loading(i++);

        }
    };
    // timer which triggers the actionlistener every 15ms
    timer = new Timer(15, listener);
    timer.start();
  }
}
Nathaniel Ford
  • 20,545
  • 20
  • 91
  • 102
Dragneel
  • 171
  • 2
  • 16
  • 1
    A [mcve] would be beneficial here. Your GUI most likely shouldn't have static methods. – OneCricketeer Mar 23 '16 at 22:01
  • To call a method of an object, you need to have a reference to that object. So A should pass a reference to itself (`this`) to B, so that B can call A's method. – JB Nizet Mar 23 '16 at 22:02
  • "*I'm trying to avoid making static methods.*" why? what do you think is wrong with static methods? Also Eclipse doesn't *insist* on anything. If you don't like a suggestion it's making, turn it off. Compilation errors, of course, are a different story. Are you getting a compilation error? Either way, actual code and error messages would be helpful. – dimo414 Mar 23 '16 at 22:03
  • 1
    @dimo414 *cannot reference non-static symbol from static context* is not a suggestion – OneCricketeer Mar 23 '16 at 22:04
  • @cricket_007 that's a compiler error, nothing to do with Eclipse. We're all just going off of the OPs vague description but I interpreted the question as referring to a method that Eclipse suggests could be static. – dimo414 Mar 23 '16 at 22:06
  • I added my code to the post. – Dragneel Mar 23 '16 at 22:08
  • 1
    @cricket_007, it calls it more than once; it's not always `0`. – ChiefTwoPencils Mar 23 '16 at 22:14

4 Answers4

3

You're going to need a reference to an instance of ClassA inside of ClassB to avoid static methods.

First, ClassB will need a field and constructor similar to the following:

private ClassA parent = null;

public ClassB(ClassA parent) {
    this.parent = parent;
}

Then, when you instantiate ClassB, you'll pass a reference to the current instance like so: ClassB name = new ClassB(this)

Finally, when you want to use your method inside ClassB (let's assume that method is called doSomething(), you can call it with parent.doSomething()

Joseph Roque
  • 5,066
  • 3
  • 16
  • 22
  • I just implemented your solution and it worked flawlessly! It had never occurred to me passing a whole class as a parameter! Thanks! – Dragneel Mar 23 '16 at 22:13
3

The "proper" OOP approach to do this would be with an interface.

public interface Loadable {
    void reset();
    void setProgress(int progress);
    void onLoaded();
}

You implement this in your Game class

public class Game extends JFrame implements ActionListener, Loadable {

    private JButton load_button;
    private JProgressBar progressBar;

    public Game() {
        // initialize
    }

    public void executeTasks() {
        //TODO do something
    }


    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource().equals(load_button)) {
            new Loader().load(this);
        }
    }

    @Override
    public void onLoaded() {
        executeTasks();
    }

    @Override
    public void reset() {
        progressBar.setValue(0);
    }

    @Override
    public void setProgress(int progress) {
        progressBar.setValue(progress);
    }
}

And pass it into the Loader. This way, the Loader doesn't care the you are giving it a Game object. You could have any implementation of Loadable that this Loader can load.

public class Loader {
    private Timer timer;
    private int i;

    public void load(final Loadable l) {
        // reset loading bar
        l.reset();
        i = 0;

        ActionListener listener = new ActionListener() {
            public void actionPerformed(ActionEvent e) {

                l.setProgress(++i);

                if (i >= 100) {
                    timer.stop();
                    l.onLoaded();
                }

            }
        };
        // timer which triggers the actionlistener every 15ms
        timer = new Timer(15, listener);
        timer.start();
    }
}
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
1

You can call non-static methods of an object, but you can only call static methods on a class. See this for more information on the difference between the two. To be able to call a method on an object of type ClassA, you'd have to do something like this:

public class ClassA {
  public method myNonStaticMethod() { ... }
}

public class ClassB {
  private ClassA a;

  public ClassB(ClassA a) {
    this.a = a;  //This makes sure this *object* has a *reference* to an object of *type* ClassA.
  }

  public void looping() {
    //some looping code
    this.a.myNonStaticMethod(); //Actually call the nonstatic method
  }
}

Note that any class that imports another class will have reference to that class and can call static methods on that class, or instantiate a new object of that class type. If you want a particular object to call a non-static method of another object, it either needs to instantiate the object itself, or it needs a reference to that other object.

In the example above, the constructor of ClassB gets a reference to a specific object of type ClassA, whose reference name is a. This is saved to a private member field, which can be called by any non-static method in an object of type ClassB.

Community
  • 1
  • 1
Nathaniel Ford
  • 20,545
  • 20
  • 91
  • 102
  • This is very similar to @JosephRoque's solution. I is exactly what I was looking for. Thanks :) – Dragneel Mar 23 '16 at 22:15
  • Agreed! Be sure you learn the correct terminology, though; the terminology describes the differences that are causing you trouble here. – Nathaniel Ford Mar 23 '16 at 22:15
0

To call any non-static method of A, you need a class instance of A. Do you have one inside class B? If you don't then you can't call a non-static method. A static method can be called without the instance (as long as it is accessible) like this A.method1();

greenrobo
  • 781
  • 1
  • 6
  • 9