java program freezes when calling another program in same jar - java

I just wanted to add space invaders as an easter egg to a program I made.
I found an open source code Here
The game runs fine on its own. However when I try to run it from a button in my program it makes my program and that game freeze. I just took his source code and added it to mine, so it is in the same jar file.
I tried 2 ways to start it.
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
Game.main(null);
}
});
}
and
plain old Game.main(null);
Should I be starting this some other way?

public static void main() {
// Start the main game loop, note: this method will not
// return until the game has finished running. Hence we are
// using the actual main thread to run the game.
SpaceInvaders si = new SpaceInvaders();
Thread SpaceInvaders = new Thread(si);
SpaceInvaders.start();
}
#Override
public void run() {
// TODO Auto-generated method stub
new SpaceInvaders().gameLoop();
}
}
Just had to create it's own thread for it.

Related

JavaFX freezes when I start the thread - I'm using Runlater command

I have a simple thread like this.
public class CameraThread extends Thread {
private AtomicBoolean runCamera;
public CameraThread(AtomicBoolean runCamera) {
this.runCamera = runCamera;
}
#Override
public void run() {
while (Main.RUNTHREAD) {
while (runCamera.get()) {
Platform.runLater(() -> {
System.out.println("Hello");
threadSleep();
});
}
}
}
private void threadSleep() {
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
And when I set runCamera to runCamera.set(true) utside from the thread, the whole GUI freezes and I cannot do anything.
This is a minimal example and I can't get it to work properly.
I have used RunLater command before, but this time, I'm sitting at a Dell precision M6400 machine from 2007. Could it happen that this machine cannot handle threads with Java?
Or how can I solve this issue?
To reproduce this issue, just type the following:
wget https://github.com/DanielMartensson/Darknet-Data-Creator/archive/main.zip
unzip Darknet-Data-Creator-main.zip
cd Darknet-Data-Creator-main
mvn javafx:run
Then click on Scan button, select a web camera (USB, laptop camera) and then press Save to folder button. Just select some arbitary folder. Then press Open camera button
The issue is that you are using Thread.Sleep() inside Platform.runLater(...), which means that you are sleeping the GUI, not your camera thread.
Try this instead, note how runLater is outside of the Platform.runLater code:
#Override
public void run() {
while (Main.RUNTHREAD) {
while (runCamera.get()) {
Platform.runLater(() -> {
System.out.println("Hello");
});
//Now thread sleep is outside of runLater:
threadSleep();
}
}
}
The only thing that should go inside the runlater is things that directly change the GUI. Any calculation, sleeping, processing, file reading etc should be kept separate.

can't get sequential behavior Java Swing [duplicate]

basically, I have this code which was initially working with console i/o now I have to connect it to UI. It may be completely wrong, I've tried multiple things although it still ends up with freezing the GUI.
I've tried to redirect console I/O to GUI scrollpane, but the GUI freezes anyway. Probably it has to do something with threads, but I have limited knowledge on it so I need the deeper explanation how to implement it in this current situation.
This is the button on GUI class containing the method that needs to change this GUI.
public class GUI {
...
btnNext.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
controller.startTest(index, idUser);
}
});
}
This is the method startTest from another class which contains instance of Question class.
public int startTest() {
for (int i = 0; i < this.numberofQuestions; i++) {
Question qt = this.q[i];
qt.askQuestion(); <--- This needs to change Label in GUI
if(!qt.userAnswer()) <--- This needs to get string from TextField
decreaseScore(1);
}
return actScore();
}
askQuestion method:
public void askQuestion() {
System.out.println(getQuestion());
/* I've tried to change staticaly declared frame in GUI from there */
}
userAnswer method:
public boolean userAnswer() {
#SuppressWarnings("resource")
Scanner scanner = new Scanner(System.in);
if( Objects.equals(getAnswer(),userInput) ) {
System.out.println("Correct");
return true;
}
System.out.println("False");
return false;
}
Thanks for help.
You're correct in thinking that it related to threads.
When you try executing code that will take a long time to process (eg. downloading a large file) in the swing thread, the swing thread will pause to complete execution and cause the GUI to freeze. This is solved by executing the long running code in a separate thread.
As Sergiy Medvynskyy pointed out in his comment, you need to implement the long running code in the SwingWorker class.
A good way to implement it would be this:
public class TestWorker extends SwingWorker<Integer, String> {
#Override
protected Integer doInBackground() throws Exception {
//This is where you execute the long running
//code
controller.startTest(index, idUser);
publish("Finish");
}
#Override
protected void process(List<String> chunks) {
//Called when the task has finished executing.
//This is where you can update your GUI when
//the task is complete or when you want to
//notify the user of a change.
}
}
Use TestWorker.execute() to start the worker.
This website provides a good example on how to use
the SwingWorker class.
As other answers pointed out, doing heavy work on the GUI thread will freeze the GUI. You can use a SwingWorker for that, but in many cases a simple Thread does the job:
Thread t = new Thread(){
#Override
public void run(){
// do stuff
}
};
t.start();
Or if you use Java 8+:
Thread t = new Thread(() -> {
// do stuff
});
t.start();

Use of Timer in BlackBerry project

I'm trying to use Timer in my BlackBerry project in this manner -
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
pushScreen(new MyScreen());
}
},200);
but I'm getting a Runtime Exception while executing the program.
Can someone please tell me what is wrong with this code? Or any other tips for using the Timer in a BlackBerry project.
My goal is to push SplashScreen for 10 sec and then MyScreen page will be open. So I want to use timer for a 10 second delay while opening the MyScreen page and during the timer I will display the SplashScreen page.
As Richard mentioned in his answer, you are having problems because you're attempting to manipulate the UI from a thread other than the main (aka "UI") thread. You just need a small change to make your code work properly:
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
pushScreen(new MyScreen());
}
},
200 /* delay */,
false /* repeat = no */);
The above is the equivalent of the code you posted, for BlackBerry Java.
My goal is to push SplashScreen for 10 sec and then MyScreen page will
be open. So I want to use timer for a 10 second delay while opening
the MyScreen page and during the timer I will display the SplashScreen
page.
If this is actually what you want to do, then just make your SplashScreen appear as soon as the app is launched:
public class MyApp extends UiApplication
{
/**
* Entry point for application
* #param args Command line arguments (not used)
*/
public static void main(String[] args)
{
// Create a new instance of the application and make the currently
// running thread the application's event dispatch thread.
MyApp theApp = new MyApp();
theApp.enterEventDispatcher();
}
public MyApp()
{
// Push a screen onto the UI stack for rendering.
final SplashScreen splashScreen = new SplashScreen();
pushScreen(splashScreen);
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
pushScreen(new MyScreen());
popScreen(splashScreen);
}
},
10*1000 /* delay in msec */,
false /* repeat = no */);
}
This does what you asked, but the link that Richard provides also allows the user to dismiss the splash screen early. That may or may not be what you want, so I simply offer the alternative above.
Hard to say what exactly is going wrong, but one thing that you should not do is interact with the user interface on a thread that is not the event thread.
It won't teach you how to use timers but there is a developer article on how to do a splash screen.
You're pushing a new screen every 200 ms...
You need to kill the timer when the screen is pushed. And remember that the interval is in milliseconds, so you need to calculate that.
Good luck!
For Android you would probably want to do something like this:
initialize();
setButtonListeners();
new Thread() {
public void run() {
try {
sleep(3000);
} catch (Exception e) {
} finally {
Intent menuIntent = new Intent(SplashLoadScreen.this,
MainMenu.class);
startActivity(menuIntent);
}
}
}.start();
I'm not too familiar with BlackBerry, but it seems like you use pushScreen() instead of startActivity(), and you don't use Intents like Android does, so perhaps something as this:
initialize(); //Method to initialize all variables you might want to use.
//...Some code
new Thread() {
public void run() {
try {
sleep(3000); //Time in milliseconds
//to make this thread sleep before executing whatever other code.
} catch (Exception e) {
} finally {
pushScreen(new MyScreen()); //Push next screen
}
}
}.start();
The try{} catch(){} finally{} thing is exception handling.
Basically, if any errors happen when it's attempting to sleep for 3000 millis, then it will catch all Exceptions (a.k.a. errors) and do whatever's in catch(){}. Then, after either the try {} (if no exceptions have been found) or the catch(){} (if errors have been found) is finished, it does whatever's in the finally{}. This case finally will push the next screen.

Why is run() getting called just once?

Consider this class, AnimationThread:
class AnimationThread implements Runnable {
public void pause() {
doAnimation = false;
}
public void doStart(){
doAnimation = true;
}
#Override
public void run() {
// TODO Auto-generated method stub
if (doAnimation) {
//my code
}
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
}
}
}
Now I am starting this thread in onCreate of an activity (just showing rough code):
AnimationThread animRunnable = new AnimationThread();
animationThread = new Thread(animRunnable);
animationThread.start();
But run() is getting called just once (I traced a log to confirm that). I just want to know that when I started the thread why run() is not getting called repeatedly with 500 sleep. It is just called once.
That is how it is supposed to be.
A Thread runs by executing its run method (just once). After that it is considered done/dead/finished/completed.
If you want to loop, you have to do it yourself (inside of the run method), or use some ExecutorService to call the Runnable repeatedly.
Of course the run() method will be executed once. If you want to repeat the statements inside the run method then you have to use loop. Take a look at TimerTask - will runs a task at a specified time or repeatedly.
EDIT:
Android - Controlling a task with Timer and TimerTask?
Timer task schedule

Problems with ActionListener and SystemUtil.invokeLater

I have look all over the web, and found no solution to my problem. For a AP Comp Sci project, I am making a Set of games, that will be run from a JFrame with JButtons. I have the games all ready, along with action listeners, but the games dont launch properly. The JFrame and JButtons are all setup correctly too.
private static class TetListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
GameCenter.quit();
GameCenter.startTetris();
}
}
GameCenter.quit() does nothing but run JFrame.dispose(), and GameCenter.startTetris(); constructs a new Tetris object, then run the play() method to start the game. All of Tetris is coded properly and works correctly when it is run in the main method (outside the actionlistener). But as soon as I put it in the ActionListener, it fails to be constructed properly. I tracked the problem down to:
public BlockDisplay(BoundedGrid<Block> board)
{
this.board = board;
grid = new JPanel[board.getNumRows()][board.getNumCols()];
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() // <<<<<<<<<<------------------- Problem Here
{
public void run()
{
createAndShowGUI(); // <<<<<<<<<<<<-------- Never Run
}
});
//Wait until display has been drawn
try
{
while (frame == null || !frame.isVisible()) // <<<<<<<-------- Never Resolved
{
Thread.sleep(1);
}
}
catch(InterruptedException e)
{
e.printStackTrace();
System.exit(1);
}
}
So the program always hangs. I also made a Pacman game that uses this SwingUtilities.invokeLater, so it doesnt work either. I cant figure out why this is happening or how to fix it.
Any help is appreciated. Let me know if you need any more info.
If the thread that runs SwingUtilities.invokeLater is already the swing event thread and you run in this while loop, yup, your application will hang.
Get rid of the while loop.

Categories