I'm working on a small Java game using Swing for school, and we need to implement a button that "starts a new game" when pressed. The problem is, the game takes multiple parameters from String[] args, so I can't just call the "main" function (where everything is instansiated) again from another class. Any way to do this?
You certainly can call main() from inside your application. But it's also certainly not what you want to do. Instead try moving the instantiation code into another function, most likely a constructor of some type of Game object. Then you can instantiate a new game from both main as well as some kind of restart function without any unintended consequences of calling main from inside your application.
You can use the following code to run a program. Unless your button and game are in the same package, be sure to import it (which will look like import packageName.className).
JButton newbutton = new JButton("New");
newbutton.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent e) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new className(); //run the class you want to here
}
});
}
});
If you have any questions about this code, please comment below.
You have to lauch your program before exit it.
Runtime rs = Runtime. getRuntime(); try { rs. exec("java -jar your_restartable_program.jar"); }
Related
EDIT:
I noticed that my question was linked to another. While our goals are similar, the other question's set up is different: they are creating all the GUI aspects of the program within the main class of their program, they are also setting the trigger event of the button press within the start method. Therefore the solution of using the "setOnAction(event->" coupled with Task works. It is a single class program, I was able to make the solution work if I created a new, single class program, this application does not work for me for my situation.
In my set up I am not running this event out of the main class, but out of the Controller class that is linked to my FXML and I have the event that triggers the method already defined. I did not post my entire Controller class as that seemed unnecessary. If there is a way to make the linked question's solution work for my different set up, or a link for guidance that would be stellar. I have looked into the "task" set up, taking from the linked question, but so far have not been able to get it to work successfully as pictured below:
#FXML
private void goForIt(ActionEvent event)
{
kickTheBaby();
}
private void kickTheBaby()
{
java.util.Date now = calendar.getTime();
java.sql.Timestamp currentTimestamp = new java.sql.Timestamp(now.getTime());
statusFld.setOnAction(event -> {statusFld.setText("Running");
Task task = new Task<Void>() {
#Override
public Void call()
{
(new Thread(new EmailCommunication("", currentTimestamp, "START"))).start();
(new Thread(new DataGathering2())).start();
return null;
}
};
task.setOnSucceeded(taskFinishEvent -> statusFld.setText(statusFld.getText()
+ "All done time to sleep..."));
new Thread(task).start();
});
}
I have a program in Java8 using FXML that downloads and parses data. I wish to make the program update the GUI TextField (called "statusFld" here) to say "Running" when I click the start button. Below is the method in the controller that should be responsible for this series of events.
#FXML
private void goForIt(ActionEvent event)
{
statusFld.setText("Running!");
java.util.Date now = calendar.getTime();
java.sql.Timestamp currentTimestamp = new java.sql.Timestamp(now.getTime());
(new Thread(new EmailCommunication("", currentTimestamp, "START"))).start();
(new Thread(new DataGathering2())).start();
}
However, when I attempt to run the program the GUI does not visually update and goes straight into the other two threads. So I attempted to utilize the "Platform.runLater()" methodology in one of the other threads by passing the status field to it as so:
Platform.runLater(() ->
{
statusFld.setText("Running!");
});
But after 20 minutes it had not given a visual update to the GUI. My guess is that this is probably due to the sheer amount of data processing that I am having it do, so who knows what "later" will actually be in this case.
My question is how can I be sure that the GUI visually updates before moving on to the other, very processing intense, threads?
Thank you!
I'm executing a Perl script via "Runtime.getRuntime().exec("perl C:/script.pl")"
as part of a Jbutton action listener. I would like to be able to click the button twice and get two instances of the same Perl script running. The script is reading in a text file so it acts a little differently depending on the text file the second time it is started but in general the script does the same thing.
I've tried to combat this by wrapping the runtime command in a new thread and executing a ".run()" on it each time the button is pressed but this only seems to interrupt the first instance and start the new one. There seems to be no way to execute two of the same Perl script in parallel. Any ideas on how I can accomplish this?
ActionListener edit = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
class GetThread implements Runnable {
public void run() {
try {
Runtime.getRuntime().exec("C:/Perl/bin/perl5.16.3.exe C:/Perl/get.pl", null, new File("C:/Perl"));
} catch (IOException e1) {
exceptionLog(e1);
}
}
}
GetThread get = new GetThread();
get.run();
}
}
http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html says
Every Java application has a single instance of class Runtime that allows the application to interface with the environment in which the application is running. The current runtime can be obtained from the getRuntime method.
It may be blocking on your call.
I'm new to Java programming and am facing a (most likely) easy problem that I don't seem to be able to get across nor understand.
I have three different java files, one where I create an interface (SimulatorGui.java), other where I am creating a panel to use on the jTabbedPanel created in the interface (CollisionPanel.java - CollisionPanel class) and a third one, where I run a code that will create the output needed (Collision.java - Colision class).
In the Collision.java main method, I am doing the following:
public static void main (String[] args) {
//<editor-fold defaultstate="collapsed" desc="Simulation start procedures">
Tally statC = new Tally ("Statistics on collisions");
Collision col = new Collision (100, 50);
col.simulateRuns (100, new MRG32k3a(), statC);
//</editor-fold>
new SimulatorGUI().setVisible(true);
CollisionPanel update = new CollisionPanel();
update.updatepanel();
The first block, will create the desired output. I then want to send that output to the updatepanel! I am not passing any arguments to the method as I am still trying to debug this. updatepanel method is created in the file CollisionPanel as following:
public void updatepanel(){
System.out.println ("debug");
jTextArea1.setText("update\n");
}
What happens then is that when I run the Collision.java file it will output the "debug" text but won't set the text to the jTextArea1 (append doesn't work aswell). I then created a button to try and do so and in that case it works. In CollisionPanel.java:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
updatepanel();
}
This does the trick! I've searched and tried different things but can't seem to understand why this won't work.
Thanks in advance for your help, hope I've made the problem clear!
Okay I think I've eventually got the problem, and it is because of the IDE, you see in your main method you initiate a new CollisionPanel, which is wrong, netbeans has already added and initiated that panel in the SimulatorGUI, so now what you need to do is add a get method in the SimulatorGUI to get the initiated panel, then call the update method on that panel.
So add this to SimulatorGUI:
public CollisionPanel getCollisionPanel1() {
return collisionPanel1;
}
replace your old updatePanel() method with:
void updatepanel(String str) {
System.out.println ("debug");
jTextArea1.setText(str);
// jTextArea1.revalidate();
jLabel1.setText("test");
}
after that change your main too look like this:
SimulatorGUI simulatorGUI = new SimulatorGUI();
simulatorGUI.setVisible(true);
CollisionPanel cp=simulatorGUI.getCollisionPanel1();
cp.updatepanel("Hi");
and dont forget to remove the old updatePanel() method call from your CollisionPanel constructor, because now you can simply call cp.updatePanel("text here"); in your SimulatorGUI class instead of calling it only in the constructor.
I hope this is easy to grasp, if you're unsure let me know
Where do you add your CollisionPanel to the main GUI? I fear that this is your problem, and that you need to do this for your code to work. In fact where do any of your three classes get a reference to the others? For different classes to work in a program, there must be some communication between them. Understand that if you create a CollisionPanel object inside the GUI, and create another CollisionPanel object inside of the main method, calling a method on one object will have no effect on the other since they are two completely distinct entities.
For example, this code:
new SimulatorGUI().setVisible(true);
CollisionPanel update = new CollisionPanel();
update.updatepanel();
It appears that you are in fact calling updatePanel() on a CollisionPanel, but it's not on any CollisionPanel that is visualized in your GUI.
Consider giving SimulatorGUI a method that allows one to pass the CollisionPanel into it so that it can use it. This may in fact be a constructor parameter:
CollisionPanel update = new CollisionPanel();
SimulatorGUI simulatorGUI = new SimulatorGUI(update);
update.updatePanel();
Meaning SimulatorGUI's constructor would have to look something like:
public SimulatorGUI(CollisionPanel update) {
this.update = update;
// add update to GUI somewhere
}
There are three different levels when developping a GUI:
The view: the graphical component
The Model: the code that you run
The controller: checks if are update on the model in order to refresh the view.
So When you first start your program, the view will have the value assigned in the code; for instance say you created your JTextArea with the initial value type here. The view will show the JTextArea with the text type here.
When a change is made to the model, the view is not aware of it, it is job of the controller to check for update on the model and then refresh the view.
So this:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
updatepanel();
}
Will generate an event that say a property has been modify. So the controller will update the view.
Other than that, the change will not appear on the view.
Hope this helps..
I am wondering what is the best way to do this? I have two packages in a Java project: game, and maker. The game is my 2d platformer, and the maker will be the map maker. The only way to switch between the two right now is manually through the run configurations. How can I make it so when the program is run, I can choose to open the game or the map maker?
Create a launcher class with a main() method, and use that as the main entry point.
Have the main() method of the launcher class allow the user to select whether they want to play or make maps, then simply call the relevant main() method from the other class:
public class Launcher {
...
public void main(String[] args) {
... decide which action is wanted ...
if (playGame) { Game.main(gameArgs); }
else if (makeMaps) { MapMaker.main(mapMakerArgs); }
}
...
}
Create two different main methods in two different classes, run the main you want to run.
Alternatively you could do something like:
public static void main(String[] args){
int option = JOptionPane.showConfirmDialog(null, "Yes to open game, no to open map maker", "Starting Up", JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_OPTION);
if(option == JOptionPane.YES_OPTION){
//start up the game
} else {
//start up the map maker
}
}
Pop a JDialog asking "Map or Play?".
I don't know what you mean by "the run configurations" but it sounds like you are talking about an IDE. How it is run in an IDE is irrelevant to an end user, who will almost certainly not be able to manually change run-time configurations.
How do you close a java application from the code?
You call System.exit:
System.exit(0);
I believe that by most standards, System.exit() is a not very OOP way of closing applications, I've always been told that the proper way is to return from main. This is somewhat a bit of a pain and requires a good design but I do believe its the "proper" way to exit
If you're terminating a Swing app, I would do an EXIT_ON_CLOSE
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
before System.exit(0). This is better since you can write a Window Listener to make some cleaning operations before actually leaving the app.
That window listener allows you to exit the app from the code:
public void windowClosing(WindowEvent e) {
displayMessage("WindowListener method called: windowClosing.");
//A pause so user can see the message before
//the window actually closes.
ActionListener task = new ActionListener() {
boolean alreadyDisposed = false;
public void actionPerformed(ActionEvent e) {
if (frame.isDisplayable()) {
alreadyDisposed = true;
frame.dispose();
}
}
};
Timer timer = new Timer(500, task); //fire every half second
timer.setInitialDelay(2000); //first delay 2 seconds
timer.setRepeats(false);
timer.start();
}
public void windowClosed(WindowEvent e) {
//This will only be seen on standard output.
displayMessage("WindowListener method called: windowClosed.");
}
If you're running an application, System.exit will work.
System.exit(int);
In an applet, however, you'll have to do something along the lines of applet.getAppletContext().showDocument("landingpage.html"); because of browser permissions. It won't just let you close the browser window.
You use System.exit(int), where a value of 0 means the application closed successfully and any other value typically means something was wrong. Usually you just see a return value of 1 along with a message printed to sysout or syserr if the application did not close successfully.
Everything is fine, application shut down correctly:
System.exit(0)
Something went wrong, application did not shut down correctly:
System.err.println("some meaningful message"); System.exit(1)