JFrame freezes while running the code continuously - java

I have problem while working with JFrame, which get freezes while
running the code continuously. Below is my code:
On clicking on btnRun, I called the function MainLoop():
ActionListener btnRun_Click = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
MainLoop();
}
};
Implementation of MainLoop():
void MainLoop()
{
Hopper = new CHopper(this);
System.out.println(Hopper);
btnRun.setEnabled(false);
textBox1.setText("");
Hopper.getM_cmd().ComPort = helpers.Global.ComPort;
Hopper.getM_cmd().SSPAddress = helpers.Global.SSPAddress;
Hopper.getM_cmd().Timeout = 2000;
Hopper.getM_cmd().RetryLevel = 3;
System.out.println("In MainLoop: " + Hopper);
// First connect to the validator
if (ConnectToValidator(10, 3))
{
btnHalt.setEnabled(true);
Running = true;
textBox1.append("\r\nPoll Loop\r\n"
+ "*********************************\r\n");
}
// This loop won't run until the validator is connected
while (Running)
{
// poll the validator
if (!Hopper.DoPoll(textBox1))
{
// If the poll fails, try to reconnect
textBox1.append("Attempting to reconnect...\r\n");
if (!ConnectToValidator(10, 3))
{
// If it fails after 5 attempts, exit the loop
Running = false;
}
}
// tick the timer
// timer1.start();
// update form
UpdateUI();
// setup dynamic elements of win form once
if (!bFormSetup)
{
SetupFormLayout();
bFormSetup = true;
}
}
//close com port
Hopper.getM_eSSP().CloseComPort();
btnRun.setEnabled(true);
btnHalt.setEnabled(false);
}
In the MainLoop() function, the while loop is running continuesly until the Running is true problem is that if i want to stop that while loop i have to set Running to false which is done at another button btnHalt:
ActionListener btnHalt_Click = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
textBox1.append("Poll loop stopped\r\n");
System.out.println("Hoper Stopped");
Running = false;
}
};
but btnHalt is not responding, whole frame is get freeze, also not
showing any log in the textarea.

Swing is a single thread framework. That is, there is a single thread responsible for dispatching all the events to all the components, including repaint requests.
Any action which stops/blocks this thread will cause your UI to "hang".
The first rule of Swing, NEVER run any blocking or time consuming tasks on the Event Dispatching Thread, instead, you should use a background thread.
This runs you smack into the second rule of Swing. Never create, modify or interact with any UI component outside of the EDT.
There are a number of ways you can fix this. You could use SwingUtilities.invokeLater or a SwingWorker.
SwingWorker is generally easier, as it provides a number of simple to use methods that automatically re-sync there calls to the EDT.
Take a read through Concurrency in Swing
Updated
Just so you understand ;)
Your MainLoop method should not be executed within the context of the EDT, this is very bad.
Also, you should not be interacting with any UI component from any thread other the then the EDT.

Related

How to achieve thread concurency in Java

I am working with a Java Swing application, where I have a main frame and multiple panels which I commute between by setting them visible or not and in the same time, I am instantiating a class which is running a while loop in the background. Now, the problem is: the panels don't appear unless that while loop ends, but I would like to let the user click some buttons while the while loops continues in the background, without even him knowing about that. Here is a small example of my code:
startPage.setVisible(false);
lblError.setVisible(false);
new QuestionPage(Integer.parseInt(fieldUserID.getText()));
QuestionPage has a while loop going, and I would like to not freeze the whole application until that is finished, but to let that while loop run in the background. So far I tried doing 2 threads by extending the Thread class, but I am not sure if this is the right way to do it.
[EDIT]
Here is my NEXT button after using a SwingWorker in order to send in background the while loop which happens in QuestionPage class and to carry on with swing operations on the main frame
btnStart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (validateInput(fieldUserID.getText(), fieldAge.getText(), fieldSex.getSelectedItem().toString(), fieldExperience.getText())) {
startPage.setVisible(false);
lblError.setVisible(false);
SwingWorker worker = new SwingWorker<Void, String>() {
#Override
public Void doInBackground() {
new QuestionPage(Integer.parseInt(fieldUserID.getText()));
return null;
}
};
} else {
lblError.setVisible(true);
}
};
});
[ANSWER]
The trick is to use a SwingWorker to send the long running task in the background and to also call execute() on it. Here is a minimal working example for a Start button event listener:
// Send long running task in background
SwingWorker worker = new SwingWorker<Void, String>() {
#Override
public Void doInBackground() {
new QuestionPage(Integer.parseInt(fieldUserID.getText()));
return null;
}
};
worker.execute();

Thread in java is not working

previous the same thread was running in java eclipse luna, but interruptions appeared I changed to Java EE IDE, the same thread which previous ran in luna now is not running in Java EE IDE, here it is
public void clockTime(){
Thread clock=new Thread(){
public void run(){
try {
for(;;){
Calendar cald=new GregorianCalendar();
day=cald.get(Calendar.DAY_OF_MONTH);
month=cald.get(Calendar.MONTH);
year=cald.get(Calendar.YEAR);
seconds=cald.get(Calendar.SECOND);
minutes=cald.get(Calendar.MINUTE);
hours=cald.get(Calendar.HOUR);
lblClock.setText("<html>"+hours+":"+minutes+":"+seconds+"<br>"+day+"/"+month+"/"+year+"</html>");
sleep(1000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
clock.start();
}
please may any one help me??.
calling the method to constructor I have already done not seen here, but if I remove the thread the method is executed since it displays the time and date as required but not changing due to absence of loop and forever loop.
If this is a Swing application then:
Make sure that you start the application on the Swing event thread, by calling SwingUtilities.invokeLater(Runnable); where your GUI is started up in that Runnable
You're making a key Swing call off of the Swing event thread (EDT) in the code above, namely the lblClock.setText(...) call. This also should be called only on the Swing event thread, in the same way as point above.
Or you could use a SwingWorker and then make the setText call in the publish / process method pair.
Or (and this is what I would do), chuck all that code above and use a Swing Timer. It's much simpler, and you wouldn't have to worry about on/off Swing event since all calls would be on the event thread.
If you go the Swing Timer route, you'd construct pass in its constructor an int equal to the desired delay, here 1000 msecs. The Timer's ActionListener is called repeatedly, and in that you'd get your time values, and then use it to create a String that you pass to your JLabel.
For example, something roughly like:
int timerDelay = 1000;
Timer timer = new Timer(timerDelay, new ActionListener() {
public void actionPerformed(ActionEvent e) {
// calculations to get time Strings
String text = ..... // use calculations above
lblClock.setText(text);
}
});
timer.start();
Note that code has not been tested

Java one code to stop in a loop and not stop the entire program in eclipse

Currently in my brief time with Java I have made a clicker game and I've been trying to implement a way to add a number to an integer (or the int command) every couple of seconds. but whatever I try just stops the entire program completely such as the
Thread.sleep(15000);
wait(15000);
even if they are in a try and catch it just stops the program and not complete a loop every couple of seconds.
If you have Thread.sleep(xxx); in the current thread, then yes, it will stop the current thread for xxx seconds. Because (most likely) Thread.sleep is in the same thread that is controlling the GUI, it is pausing your code from executing, freezing your application. There are two ways you can fix this:
Create a new thread and place the timer code in there:
SwingUtilities.invokeLater will add your Runnable to the queue of threads that AWT executes.
// Because the code is in a different thread, Thread.sleep(1000) will not pause
// the current thread and the application will continue as normal
Thread thread = new Thread(new Runnable() {
int seconds = 0;
#Override
public void run()
{
while (true) {
// wait one second
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
};
// increment seconds
seconds++;
System.out.println(seconds);
}
}
});
thread.start();
Use an existing timer in the Java API
Look at ScheduledThreadPoolExecutor and its scheduleAtFixedRate method. Here's an example. You could also use a swing timer as mentioned in the comment by Hovercraft Full Of Eels.
To use a Swing timer, you import javax.swing.Timer (not java.util.Timer), create a Timer object with the delay and an action listener listening for when it will fire events, and start it.
Timer timer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent a)
{
System.out.println("Timer went off!");
}
});
// Repeat every second
timer.start();
Note that this code won't execute on its own; you need to have a GUI running.

libgdx - doing something in other thread not working

My game has a stats queue, after each game the current game stats goes into the queue.
Whenever the mainmenu starts i want to upload all the game stats to a server, and this take like 1-3 seconds and I want to do this in an other thread.
My code
#Override
public void show() {
Global.key = Global.getKey();
// System.out.println(Stats.getJSONObject(Global.key));
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
Stats.TryUploadGame1();
System.out.println("DONE");
}
});
.....
}
But this also freezes my game.
What should I do?
Your current code is posting a Runnable instance that will be executed by the render thread before the next frame. The Gdx.app.postRunnable API is generally used so background threads can ask for something to happen on the render thread. You want to post a Runnable to execute anywhere but the render thread.
As long as your Stats code doesn't interact with OpenGL context at all (since Android OpenGL APIs assume only a single thread interacts with them), you can just post your Runnable on a new background thread:
new Thread(new Runnable() { ... }).start();
This should unblock your render. (Of course, if your background thread uses a lot of CPU, it can still interfere with the render thread, but if its mostly doing blocking IO or host has spare cores, it shouldn't interfere.)
This could be improved in lots of ways (using a ThreadPool, or using Android-aware background task support), but if your stats update is relatively quick and the thread creation isn't frequent this should work fine.
Okay to do something in a other thread you need to take care of the OpenGL context. Inside of a different thread you cant do anything that does render stuff. You are forced to push such thing into the renderthread in any way. And you need to synchronize everything that can be called from the regular render thread from libgdx. For example you want to call the .act(float delta) from a stage from a different thread you are forced to put the stage indo an synchronized block.
The post runable isn't a thread. It is an runable that get executed at the beginning of the next rendercall. So it will stop the game till it's done but it is inside of the OpenGl context thread. (That's why your game stops)
So here is an example of how to use threading in libgdx. I use this inside of my game. It runs on 210 frames so 210 updatecalls per second. You can change it to as fast as possible or just to 60fps whatever you need:
public class GameLogicThread extends Thread {
private GameScreen m_screen;
private boolean m_runing;
private long m_timeBegin;
private long m_timeDiff;
private long m_sleepTime;
private final static float FRAMERATE = 210f;
public GameLogicThread(GameScreen screen) { //pass the game screen to it.
m_screen = screen;
setName("GameLogic");
}
#Override
public void run() {
m_runing = true;
Logger.log("Started");
while (m_runing) {
m_timeBegin = TimeUtils.millis();
// act of the camera
synchronized (m_screen.figureStage) { //stage with figures
// now figures
if (m_screen.m_status == GameStatus.GAME) {
m_screen.figureStage.act(1f / GameLogicThread.FRAMERATE);
}
}
m_timeDiff = TimeUtils.millis() - m_timeBegin;
m_sleepTime = (long) (1f / GameLogicThread.FRAMERATE * 1000f - m_timeDiff);
if (m_sleepTime > 0) {
try {
Thread.sleep(m_sleepTime);
}
catch (InterruptedException e) {
Logger.error("Couldn't sleep " + e.getStackTrace());
}
} else {
Logger.error("we are to slow! " + m_sleepTime); //meight create it dynamic so if you are to slow decrease the framerate till you are not to slow anymore
}
}
}
/**
* Stops the thread save<br>
*/
public void stopThread() {
m_runing = false;
boolean retry = true;
while (retry) {
try {
this.join();
retry = false;
}
catch (Exception e) {
Logger.error(e.getMessage());
}
}
}
}
This does update all my figures. To not cause any troubles with the rendering thread the figurestage is synchronized. (Kind of critical section)
Dont forget that you need to create a new thread every time you stopped it. so for example inside of the show you need todo this:
#Override
public void show() {
super.show();
m_logic = new GameLogicThread(this); //create a new one inside of the GameScreen
m_logic.start(); //start the thread
}
Also dont forget to savestop it inside of the pause stop and so on.
#Override
public void dispose() {
m_logic.stopThread();
}
According to the wiki
To pass data to the rendering thread from another thread we recommend using Application.postRunnable(). This will run the code in the Runnable in the rendering thread in the next frame, before ApplicationListener.render() is called.
So calling that method is just creating a new thread on to run on the render thread.
You may want to use standard java practice on creating threads unless this is frowned upon in libgdx because of android, that I am not sure of.

GUI Threading in Java (and SwingUtilities)

I'm making a simple game in Java using swing and am having problems with my GUI freezing up sporadically (due to threading issues most probably) after a button press that is supposed to trigger a switch in JPanels.
I posted a related thread here, which has more details about the actual code I'm currently using (although I did update the countdown and get that working fine). From answers to that thread, it seems like usingSwingUtilities.invokeLater() or invokeAndWait() might be what I need to solve the problem, but I'm not sure where in my code it is necessary or exactly how to implement it.
I don't know that much about threading and could use any help (preferably somewhat detailed and with some sample code) that I can get. Let me know if any further details would be useful.
See: Tutorial: Concurrency in Swing
Generally speaking, the Event Dispatch Thread is a single thread, chugging through the event queue, processing one at a time.
SwingUtilities.invokeLater(..)
puts a Runnable on this queue. So it will be processed by the EDT when the EDT finishes everything on the queue before it (This is why sleeping on the queue blocks other events like repainting). It's relatively unusual to call invokeLater(..) from the EDT itself, though there are situations where it is useful (usually as a hack). I don't think I have had a legitimate use for SwingUtilities.invokeAndWait(..) in the last 6 years. Maybe once.
javax.swing.Timer can be configured to fire once or periodically. When it fires, it puts an event on the EDT queue. If you have computationally-intensive processing that need to be done, consider using javax.swing.SwingWorker to do the computation on another thread, and give you back the result in a thread-safe manner (this is also comparatively rare).
A good point to look is the docs. In your case, this explains how SwingUtilities.invokeLater() works and where to use it:
Causes doRun.run() to be executed asynchronously on the AWT event
dispatching thread. This method should be used when an application
thread needs to update the GUI.
So, in your actions that modifies the GUI you must use the invokeLater method to assure that the GUI wont freeze.
Another good resource is the Java tutorials. They cover concurrency in Swing.
I have create a WorkerThread class which take care of Threads and GUI current/main thread . i have put my GUI application in construct() method of WorkerThread when an event fire to start XXXServer then all threads are activate and GUI work smoothlly wihout freeze. have a look.
/**
* Action Event
*
* #see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
public void actionPerformed(ActionEvent ae) {
log.info("actionPerformed begin..." + ae.getActionCommand());
try {
if (ae.getActionCommand().equals(btnStart.getText())) {
final int portNumber = 9990;
try {
WorkerThread workerThread = new WorkerThread(){
public Object construct(){
log.info("Initializing the XXXServer ...");
// initializing the Socket Server
try {
XXXServer xxxServer = new XXXServer(portNumber);
xxxServer.start();
btnStart.setEnabled(false);
} catch (IOException e) {
// TODO Auto-generated catch block
log.info("actionPerformed() Start button ERROR IOEXCEPTION..." + e.getMessage());
e.printStackTrace();
}
return null;
}
};workerThread.start();
} catch (Exception e) {
log.info("actionPerformed() Start button ERROR..." + e.getMessage());
e.printStackTrace();
}
} else if (ae.getActionCommand().equals(btnStop.getText())) {
log.info("Exit..." + btnStop.getText());
closeWindow();
}
} catch (Exception e) {
log
.info("Error in ServerGUI actionPerformed==="
+ e.getMessage());
}
}
In order to invoke an action in the existing WorkerThread, one would intuitively send a user defined event using SwingUtilities.invokeLater() to a JFrame's actionPerformed() method as
class TestFrame extends JFrame implements ActionListener
{
...
private class Performer implements Runnable
{
ActionEvent event;
Performer(ActionEvent event)
{
this.event = event;
}
#Override
public void run()
{
actionPerformed(event);
}
}
synchronized protected void invokeLater(ActionEvent event)
{
SwingUtilities.invokeLater(new Performer(event));
}
public void actionPerformed(ActionEvent event)
{
...
}
}
Now, TestFrame.invokeLater() called in any Thread will be processed in TestFrame.actionPerformed() in existing WorkerThread .

Categories