Swing Application Starter

Hello

Just so that I do not waste more time on this.

I want a simple GUI to configure my game. And manage network games. A Simple Game lobby.

And in the end start the game client.

I have implemented this in Swing becouse at this stage I just want something really simple.

My game client main class extends SimpleApplication and I start and run this from my swing application.

I want the game to run in it’s own window in full screen. And during the time you play the game the Swing app can be in the background. This was my plan anyway.



Anyway …



When doing so I get this error:

ALLVARLIG: Uncaught exception thrown in Thread[AWT-EventQueue-0,6,main]

java.lang.IllegalStateException: Cannot run from EDT

So, my question is…

  1. Am I trying to do something that is not supported by JME? Start the game itself from a Swing application.
  2. If it should work then what am I doing wrong? Or what can I do to avoid it?

Try creating a new Thread, and starting jME from that:



[java]

Thread t = new Thread(new Runnable() {

@Override

public void run() {

YourJmeApp a = new YourJmeApp();

a.start();

}

});

t.start();

[/java]



Here’s a working example:

[java]

package test;



import java.awt.BorderLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;



import javax.swing.JButton;

import javax.swing.JFrame;



public class TestSwing implements ActionListener {



private static JButton btnNewButton;



public static void main(String[] args) {



TestSwing t = new TestSwing();

}



public TestSwing() {



JFrame f = new JFrame();



btnNewButton = new JButton(“New button”);

btnNewButton.addActionListener(this);

f.getContentPane().add(btnNewButton, BorderLayout.CENTER);

f.pack();

f.setVisible(true);

}



public void actionPerformed(ActionEvent e) {

if (e.getSource() == btnNewButton) {

btnNewButtonActionPerformed(e);

}

}



protected static void btnNewButtonActionPerformed(ActionEvent e) {



Thread t = new Thread(new Runnable() {



@Override

public void run() {

TestPssmShadow2 t = new TestPssmShadow2();//This would be your jME app extending SimpleApplication

t.start();

}

});

t.start();

}

}

[/java]



You might want to read over this some time also. (That link shows you how to run jME as a part of a Swing app, so it’s not 100% the same, but you might find it useful later.)

I am starting the JME3 parts like this. I have a button in my Swing app that run the following code to start the game client:



new Runnable() {

public void run() {

ClientMain app = new ClientMain(networkConnection, settings);

app.start();

}

}.run();



Running the same code directly in main() for example works just fine. Anything else I can do to avoid having trubble with the EDT and still keep my Swing Lobby?

Sweet! I changed my code according to your example and it worked very good.



Thanks a lot.



But what is the diffrence? Do my code not start a new thread?

Runnable doesn’t create a new Thread by itself (it’s meant to be passed to and executed by a Thread), so no it wasn’t. You can see this in the debugger (for Eclipse, not sure what NB does) if you set a breakpoint in the first line of your run() method (of the code you posted), because it’ll show the name of the thread as “[AWT-EventQueue0]”.

The issue is that jME3 starts a settings dialog which runs on the EDT, and at the end of the dialog the actual application starts. While the dialog is open, jME3 waits for a response from it so that means the application cannot be started on the EDT

Ok, that explains it.



Another question regarding Threads.



At the moment I have a Swing application that start both the Server and Client in it’s own thread like above.



Is there a performance penallty to concider running the game like this Compared to have a dedicated Server

and a dedicated Client running on there own JVM?

The reason why dedicated servers are created is generally because the GUI portion of the application can slow down the server simply by running in the background.

Also the memory requirements and usage for a server and a client are vastly different. When they share a VM they are competing for the same heap and the client GUI side of the application is usually messing up any chance the server has of doing efficient memory use or garbage collection.



For example, the Mythruna server stand-alone can run for days without executing a full GC, relying only only the iterative generational garbage collection for the short-lived objects it creates during processing. Where as the client causes full GC quite frequently.



It’s possible to run them in the same VM but the server performance would suffer because of it. For only hosting a few players, maybe the performance loss wouldn’t be enough to matter.

One way of avoiding the performance slowdown is connecting the GUI to the server through a remote machine to administer it.

Hello, I’m a new user of JME3

I try your code tebriel and it works fine but I’d like to open a new simpleApplication every time I click on the New Button (not just one time) and it doesn’t work, it freezes. How can I do ? I’m not sure but I think that we can not run 2 simpleApplication at the same time. If so is there an other way to do that ?


@tebriel said:
Try creating a new Thread, and starting jME from that:

[java]
Thread t = new Thread(new Runnable() {
@Override
public void run() {
YourJmeApp a = new YourJmeApp();
a.start();
}
});
t.start();
[/java]

Here's a working example:
[java]
package test;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

public class TestSwing implements ActionListener {

private static JButton btnNewButton;

public static void main(String[] args) {

TestSwing t = new TestSwing();
}

public TestSwing() {

JFrame f = new JFrame();

btnNewButton = new JButton("New button");
btnNewButton.addActionListener(this);
f.getContentPane().add(btnNewButton, BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}

public void actionPerformed(ActionEvent e) {
if (e.getSource() == btnNewButton) {
btnNewButtonActionPerformed(e);
}
}

protected static void btnNewButtonActionPerformed(ActionEvent e) {

Thread t = new Thread(new Runnable() {

@Override
public void run() {
TestPssmShadow2 t = new TestPssmShadow2();//This would be your jME app extending SimpleApplication
t.start();
}
});
t.start();
}
}
[/java]

You might want to read over this some time also. (That link shows you how to run jME as a part of a Swing app, so it's not 100% the same, but you might find it useful later.)