Hi i'd like to do a task out of the EDT because i don't want to froze my interface each time i click on a button :
The long-time task is the function paintComponent of fBPC then i have to create new thread for fBPC.repaint(). But even with this new thread my interface still freeze ( because i'd like to click on my button while the task is done in background ), how can i do? Maybe should i create the thread in an other part ?
new Thread(new Runnable(){
#Override
public void run() {
// TODO Auto-generated method stub
fBPC.repaint();
System.out.println("toto");
if (SwingUtilities.isEventDispatchThread()){
System.out.println("titi");
}
}
}).start();
Related
I've got a class that creates and runs a thread, which creates a GUI.
I want the initial class to remain suspended until the GUI is closed (OK button for example)
I tried thread.join(); but since the GUI is created on the event dispatch thread this does not seem to work, and the class continues as the GUI pops up.
private void CreateAndRunThread(){
GUIMaker GM= new GUIMaker(data);
GM.run();
try {
TFM.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MessageDialog.showDialog("GM Done");
}
thread's GUI creation:
#Override
public void run() {
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Turn off metal's use of bold fonts
UIManager.put("swing.boldMetal", Boolean.FALSE);
CreateAndShowGUI(frame); //adds frame, packs and sets visible
}
});
}
Use CountDownLatch:
CountDownLatch latch = new CountDownLatch(1);
Call the following in the inital class to block:
latch.await();
Call the following when the GUI is closed:
latch.countDown();
Also it seems that you are not starting thread properly. You need to call GM.start() method instead of GM.run().
May be it is a basic question. But I'm a little confused about it. In my design I've a thread that is started from a mouse click. Method looks something like this:
Runnable r = new Runnable(){
public void run(){
A.firstMethod();
A.SecondMethod();
B.FirstMethod();
B.SecondMethod();
B.ThirdMethod();
}
};
new Thread(r).start();
Here B.FirstMethod(), B.SecondMethod(), B.ThirdMethod(); are accessing same variables and do some database operations during execution (i.e. locking, reading, writing etc.). But, If mouse is clicked during the execution or before finishing all the tasks I often get error message from database. How can I handle such type of situations. Here I cannot force the user to wait just with a simple Progressbar.
To handle such situation, you can disable the button once the thread has started its execution, and enable it again once the thread is going to finish its execution.
The code will then look like following:
Runnable r = new Runnable()
{
public void run()
{
button.setEnabled(false);
A.FirstMethod();
A.SecondMethod();
B.FirstMethod();
B.SecondMethod();
B.ThirdMethod();
button.setEnabled(true);
}
};
new Thread(r).start();
Or when the button is clicked, you can use a boolean variable to check if the thread is in progress or not, and then decide as to what needs to be done like:
volatile boolean inProgress = false; // Instance Variable
Runnable r = new Runnable()
{
public void run()
{
inProgress = true;
A.FirstMethod();
A.SecondMethod();
B.FirstMethod();
B.SecondMethod();
B.ThirdMethod();
inProgress = false;
}
};
if(!inProgress)
new Thread(r).start();
else
Popup some message perhaps
i have action list which is a ArrayList. Object Action contains 3 parameters(button, action, time_it_takes). So what i have to is get a action form ArrayList perform it and wait for a while and then next action and so on. I have tried but nothing is updating in view it just hang for sometime and nothing updated. I have tried runOnUiThread but it also gives me error. Actually, i think i have weak multithreading concepts. Here is what i am trying...
public void replay()
{
ArrayList<Action> actions = gui.getActionList();
for(i =0; i<actions.size(); i++)
{
gui.Replay(actions.get(i));
try
{
Thread.sleep(actions.get(i).getTime()); // delay for the next task
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Help Please
From your comments you are calling replay() from your activity which runs on the ui thread
You are calling sleep on the ui thread which blocks the ui thread. You should not block the ui thread. Do not call Thread.sleep(2000) in the ui thread.
http://developer.android.com/training/articles/perf-anr.html
You can use a Handler if you wish you execute something every few seconds.
Handler m_handler;
Runnable m_handlerTask ;
m_handler = new Handler();
m_handlerTask = new Runnable()
{
#Override
public void run() {
// do something every 1 second
m_handler.postDelayed(m_handlerTask, 1000);
}
};
m_handlerTask.run();
To cancel the run
m_handler.removeCallbacks(m_handlerTask);
I am interfacing with a JNI that allows me to use a fingerprint scanner. The code I have written takes the scanned ByteBuffer parsed back to it by the JNI and turns it into a BufferedImage for saving.
What I can't figure out is how to wait for the scan thread to finish before the the jlabel icon on my GUI tries to update. What would be the easiest way to do this?
What else do I need to add?
Edit:
//Scanner class
Thread thread = new Thread() {
public void run() {
// [...] get ByteBuffer and Create Image code
try {
File out = new File("C:\\Users\\Desktop\\print.png");
ImageIO.write(padded, "png", out);
// [???] set flag here
} catch (IOException e) {
e.printStackTrace();
}
}
};
thread.start();
return true;
//Gui class
private void btnScanPrintActionPerformed(java.awt.event.ActionEvent evt) {
Scanner scanPrint = new Scanner();
boolean x = scanPrint.initDevice();
//Wait for the scanning thread to finish the Update the jLabel here to show
//the fingerprint
}
Not sure if you are using Swing or Android for UI but you would want to notify the main event dispatch thread (in swing it is called just that). You would run the scanning thread, then when complete send a 'message' to the EDT with the action that you want to be done to the button.
Thread thread = new Thread(new Runnable(){
public void run(){
//scan
SwingUtiltilies.invokeLater(new Runnable(){
//here you can update the the jlabel icon
public void run(){
jlabel.setText("Completed");
}
});
}
});
In UI development there is no waiting for an action to complete because you always want the EDT to be responsive.
at the end of a the scan thread, use SwingUtilities.invokeLater() to update the gui with the results of the scan.
I would like to get a recurring call back to invalidate a view. I am sure there is a neat way to do this. I am currently doing this and would like a neater / better solution if possible?
new Thread()
{
#Override
public void run()
{
while (!Thread.currentThread().isInterrupted())
{
handler.post(new Runnable()
{
public void run()
{
BannerButton.this.invalidate();
}
});
try
{
Thread.sleep(50); // yields 20 fps
} catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
}
}
}.start();
For a single shot timer on the UI thread, I do this: (But I cant find a way to do this with repeats)
(new Handler()).postDelayed(new Runnable()
{
#Override
public void run()
{
// Do stuff
}
}, SPLASH_SHOW_TIME);
Timer looked good, but it calls on a background thread.
Thanks.
Your second try using Handler is already correct. Just store the Handler and the Runnable in a field, and then inside the run() method (possibly at the end), call again
handler.postDelayed(runnable, 1000);
Look at the View.postInvalidate() method. This is different from invalidate() as you can do it from any Thread you want. It just posts an invalidate() message in the UI thread Looper
Concerning your second question simply post with some delay the same Runnable at the end of the Runnable in your Handler