0

So I have a MainWindow.java that creates the window with all the controls and things. I put a menubar object on the window, one of the options in the menubar is make the program a server. So here's the main window looks like this:

public class MainWindow extends javax.swing.JFrame {
     //all code including menubar click action handler
     //Server.start()
}

When you click the option, it goes into the Server.java class and starts the server. Here's the skeleton of that class:

public class Server {

    public static void start(String port) {
        try {
            startServer(Integer.parseInt(port));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void startServer(int PORT) throws Exception {
        ...
    }

    private static class ClientListenThread extends Thread {

        public ClientListenThread(Socket socket, int ClientNumber){
            ...
        }

        public void run() {
            ...
        }
    }

    private static class ServerSendThread extends Thread {

        public ServerSendThread(Socket socket) {
            ...
        }

        public void run() {
            ...
        }
    }
}

The problem now is that once it gets inside the Server class, it listens for connections and connects fine but I just can't go back to the MainWindow class. It stays within the Server class. I can't even call the MainWindow functions by doing MainWindow.function() because it says

Cannot make a static reference to the non-static method function() from the type MainWindow

I even tried putting all of the Server class code into the MainWindow class or just above it but Java didn't like that and said it wanted it in a separate file.

How exactly do I reference MainWindow functions from within the Server class? Or is there a better way of going about this?

Richard
  • 5,840
  • 36
  • 123
  • 208

1 Answers1

1

You need to either create an instance of the MainWindow class using for instance MainWindow m = new MainWindow() and then calling the function as m.function(), or declare your function as static.

Static means that you can call a function without creating an instance of the object. This is why you get the error, since your function is not static, so it requires an instance of the object to be called.

You'll also want to make sure that the MainWindow class is imported into the Server class.

Sterling Graham
  • 565
  • 3
  • 10
  • I have 1 more problem. So the `MainWindow` class has the menubar, when you select the server option from the menubar-a popup window appears. This popup window is handled by another class called `ServerWindow`. It has some fields where you can enter things in like port number then click OK. Once you click okay, `ServerWindow` sends all the typed information to the `Server` class. There's a `MainWindow` function called `draw()` that has something like: `Graphics g = this.getGraphics();`. – Richard Mar 26 '14 at 00:08
  • When I call `draw()` from `ServerWindow`, `this.getGraphics()` references Server's window rather than the original window where the menubar is. How do I fix that? – Richard Mar 26 '14 at 00:08
  • 1
    You can pass in a reference to the MainWindow object in the constructor of the ServerWindow class. Then call the draw() function on the MainWindow object that you passed in. – Sterling Graham Mar 26 '14 at 00:11
  • I tried making a class variable inside of `MainWindow`, and then initializing it inside the constructor with `mw = this.getGraphics();`. But when I called the `draw()` function from `Server` the `mw` object was null. So it is possible to initialize it and hold the value without erasing it, something like static i guess...? – Richard Mar 26 '14 at 00:14
  • 1
    I believe this is because there is nothing to be painted to the screen when the MainWindow constructor is called so getGraphics returns null. So it is better to pass in the reference to MainWindow itself when ServerWindow is created, then call the getGraphics function on the MainWindow instance when needed in the ServerWindow class. – Sterling Graham Mar 26 '14 at 00:25
  • and one LAAAAST thing. So in the mainwindow is a square that you can move around the canvas with your arrow keys. The point of this is to setup a connection between two instances of the program and have the client control the movements that will show up on the server screen. The problem I am having right now is the code, for both the server and client, is stuck in `Server.java` or `Client.java`. Therefore, since I am not in `MainWindow` I cannot control anything. Is there a way to break out of these classes and go back to `MainWindow` WITHOUT losing the connection? – Richard Mar 26 '14 at 00:47
  • 1
    The connection should be running on a separate thread than the `Server` / `Client`'s GUI thread (`MainWindow`). So what will happen is the `Server` receives a message from the `Client` to move the square, then the `Server`'s socket thread will receive the message in a `Socket.receive()` call. The thread running the socket on the Server then sends a message to the GUI thread to update the GUI's display, and afterwards continues listening for more messages. – Sterling Graham Mar 26 '14 at 01:06
  • the thing is, there are also on-screen controls (Up, down, left, right) that are created from the `MainWindow` class. They are totally unclickable since the program is inside the `Server` or `Client` class. – Richard Mar 26 '14 at 01:23
  • Do you mean that the buttons in the GUI can't be clicked at all? Like the program freezes completely? If so then you have a socket operation running on the GUI thread. [This tutorial](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html) could be helpful for what you want to accomplish with the client thread – Sterling Graham Mar 26 '14 at 01:44
  • it doesn't *freeze* per say in the sense that it turns into a white screen and crashes. It's just not an accessible window, clicking on the buttons won't do anything, since the program is in a different class. So I should use SwingWorker in `MainWindow` then? – Richard Mar 26 '14 at 02:27
  • Ah that's good then. Scratch the SwingWorker mentioned in the tutorial. I realized it's probably not the best idea to have a long running socket using it. – Sterling Graham Mar 26 '14 at 02:34
  • 1
    You can pass in a reference to `MainWindow` in the `Server` and `Client` constructors and then update the `MainWindow` GUI using `SwingUtilities.invokeLater()`. – Sterling Graham Mar 26 '14 at 02:37