I am new to java
I have a function runner inside PhotoPoster class (PhotoPoster class is a Jframe with lots of buttons and other GUI elements)
it contains a START button when I click on START it executes the runner function which runs an activity & thats takes a very long time
and other GUI components are not accessible unless the runner functions completes.
I want this to work in separate thread or any other solution to help me
what I currently do is
I have made a another class GuiWorker.java
public class GuiWorker extends SwingWorker<Integer, Integer>{
public GuiWorker() throws IOException {
}
protected Integer doInBackground() throws Exception {
PhotoPoster photoPoster = new PhotoPoster();
photoPoster.ruuner();
return 0;
}
protected void done() {
System.out.println("done");
}
}
PhotoPoster.java
on button click
private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {
// PhotoPoster photoPoster = new PhotoPoster();
//ruuner();
EventQueue.invokeLater( new Runnable() {
#Override
public void run() {
try {
new GuiWorker().execute();
} catch (IOException ex) {
Logger.getLogger(PhotoPoster.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
it gives system out done but not performing runner function activity
Please Help me to sort out this error or any other solution
It looks as though you are queuing your long running thread back onto the Event Dispatch Thread, which means that even though you are doing invokeLater it will still block the thread.
You need to use a SwingWorker.
Related
I changed my IDE from Eclipse to IntelliJ IDEA. The new one started complaining about my code.
public class Controller {
private OknoGlowne frame;
private MenuListener menuListen = new MenuListener(this);
private TabListener tabListener = new TabListener(this);
public OknoGlowne getFrame() {
return frame;
}
public Controller(){
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
frame = new OknoGlowne();
frame.setVisible(true); //error
frame.addMenuListener(menuListen);
frame.addTabListener(tabListener);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
So I commented this line. And add new line to constructor of UI frame.
public OknoGlowne() {
jPanel.setVisible(true);
}
App start but UI doesn't show any more. IDEA create frame in different way than Eclispe. I have to switch.
Main
public class Runner {
public static void main(String[] args) {
new Controller();
}
}
This doesn't really have anything to do with your IDEs. I bet if you ran it 100 times in eclipse, or from the command line, you'd get different results depending on how busy your system is.
The reason you aren't seeing the JFrame pop up is because you're using invokeLater() instead of invokeAndWait().
The invokeLater() method immediately returns, at which point you're in a race condition: will the event thread display the EDT first, or will the main thread exit first? If the main thread exits first, then your program will exit before any windows are shown.
To prevent this, you have to use invokeAndWait() instead of invokeLater().
I come from .NET environment where event listening is pretty easy to implement even for a beginner. But this time I have to do this in Java.
My pseudo code:
MainForm-
public class MainForm extends JFrame {
...
CustomClass current = new CustomClass();
Thread t = new Thread(current);
t.start();
...
}
CustomClass-
public class CustomClass implements Runnable {
#Override
public void run()
{
//...be able to fire an event that access MainForm
}
}
I found this example but here I have to listen for an event like in this other one. I should mix them up and my skill level in Java is too low.
Could you help me elaborating a optimal solution?
I think that what you are looking for is SwingWorker.
public class BackgroundThread extends SwingWorker<Integer, String> {
#Override
protected Integer doInBackground() throws Exception {
// background calculation, will run on background thread
// publish an update
publish("30% calculated so far");
// return the result of background task
return 9;
}
#Override
protected void process(List<String> chunks) { // runs on Event Dispatch Thread
// if updates are published often, you may get a few of them at once
// you usually want to display only the latest one:
System.out.println(chunks.get(chunks.size() - 1));
}
#Override
protected void done() { // runs on Event Dispatch Thread
try {
// always call get() in done()
System.out.println("Answer is: " + get());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Of course when using Swing you want to update some GUI components instead of printing things out. All GUI updates should be done on Event Dispatch Thread.
If you want to only do some updates and the background task doesn't have any result, you should still call get() in done() method. If you don't, any exceptions thrown in doInBackground() will be swallowed - it is very difficult to find out why the application is not working.
As I am using gui and I need to create a thread to complete a task. See I want to display a dialog letting the user know the task has been completed I have tried
if(!thread.isAlive()) {
JOptionPane.showMessageDialog(null, "Done");
}
But that doesnt work.
Can anyone help me
Thanks
One option is to do your work using a SwingWorker. Override the done() method and have it notify your GUI that work is complete.
A simple example that nearly matches your use case is shown in the Javadocs at the top of the page:
final JLabel label;
class MeaningOfLifeFinder extends SwingWorker<String, Object> {
#Override
public String doInBackground() {
// Here you do the work of your thread
return findTheMeaningOfLife();
}
#Override
protected void done() {
// Here you notify the GUI
try {
label.setText(get());
} catch (Exception ignore) {
}
}
}
You could just have the thread print a message as it's last line of code in it's run method:
Thread thread = new Thread() {
#Override
public void run() {
//whatever you want this thread to do
//as the last line of code = the thread is going to terminate
JOptionPane.showMessageDialog(null, "Done");
}
}
thread.start();
If you want the main thread to wait for the thread to finish, in the main thread's code you'd use:
thread.join();
create a listener in your main Thread, and then program your Thread to tell the listener that it has completed.
public interface ThreadCompleteListener {
void notifyOfThreadComplete(final Thread thread);
}
then create the following class:
public abstract class NotifyingThread extends Thread {
private final Set<ThreadCompleteListener> listeners
= new CopyOnWriteArraySet<ThreadCompleteListener>();
public final void addListener(final ThreadCompleteListener listener) {
listeners.add(listener);
}
public final void removeListener(final ThreadCompleteListener listener) {
listeners.remove(listener);
}
private final void notifyListeners() {
for (ThreadCompleteListener listener : listeners) {
listener.notifyOfThreadComplete(this);
}
}
#Override
public final void run() {
try {
doRun();
} finally {
notifyListeners();
}
}
public abstract void doRun();
}
NotifyingThread thread1 = new OneOfYourThreads();
thread1.addListener(this); // add ourselves as a listener
thread1.start(); // Start the Thread
then, as each Thread exits, your notifyOfThreadComplete method will be invoked with the Thread instance that just completed. So now you can run any of your code in this method.
Use Callable thread. It will return value,So we can identify that it completed its task.
i have one problem with handling the thread in android ,in my class i have to create one thread which create some UI after that thread finish i will get some value ,here i want to wait my Main Process until the thread complete it process but when i put wait() or notify in Main process thread does not show the UI in my application
this is sample code
protected void onCreate(Bundle savedInstanceState) {
downloadThread = new MyThread(this);
downloadThread.start();
synchronized(this){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
String test=Recognition.gettemp();
public class MyThread extends Thread {
private Recognition recognition;
public MyThread(Recognition recognition) {
this.recognition = recognition;
// TODO Auto-generated constructor stub
}
#Override
public void run() {
synchronized(this)
{
handler.post(new MyRunnable());
}
notifyAll();
}
}
}
static public class MyRunnable implements Runnable {
public void run() {
settemp(template);
}
}
}
public static String gettemp() {
return template;
}
public static void settemp(String template) {
Recognition.template = template;
}
}
here i will not use AsynTask because i have some other issue that is reason i choose Thread even now the problem is Thread wait do any give the suggestion for this
- Use java.util.CountDownLatch , here you can let some process complete before kick-off some other code.
- countDown() and await() will be of use to you.......
See this example of CountDownLatch:
http://www.javamex.com/tutorials/threads/CountDownLatch.shtml
Use the logic below :-
new Thread(new Runnable()
{
#Override
public void run()
{
//do the code here such as sending request to server
runOnUiThread(new Runnable()
{
#Override
public void run()
{
//do here the code which interact with UI
}
});
}
}).start();
What do you expect to happen if you freeze the main UI thread?
You should be using an ASyncTask to show your gui in the onPreExecute method, do the task in doInBackground then display the result in the onPostExecute method.
As a plus you can update the progress using onProgressUpdate too.
This is not an solution just a advice on how should you structure you activity/app.
You should never block the main thread by calling wait() its a bad user experience and not advised. It would also case a Android Not Responding (ANR) popup.
You can have you thread updating the UI from the background and let the UI to be responsive. Load the static part of your UI in onCreate() and then fire up the background thread to lazy load rest of the component.
I am developing a swing applciation. In that I have a workflow of jobs to be done.
I Am running these jobs in a for loop one after the other. The interesting thing is I have to update GUI status bar with the current job name running.
I can not use SwingUtilities.invokeAndWait as it can not run on the dispatch thread which will be the currently running thread.
I tried using SwingWorker since the jobs are running in a loop, the SwingWorker's doBackGrount() method will execute and will come out and gets the the next index to run the next job. In the done() of SwingWorker I have written code to update GUI with the status.
public class TestAction extends SwingWorker<Boolean, Void> {
boolean executeThread = false;
public TestAction() {
}
#Override
protected Boolean doInBackground() throws Exception {
executeThread = ExecuteWebServiceAction.webServiceExecution();
return executeThread;
}
#Override
protected void done() {
try {
boolean isOver = (boolean) get();
if (isOver) {
MainApplication.getInstance().getFrame().setStatus(LangUtil.getString("cdsExecuteFinehed")
+ " " + ((WebServiceTool) DrawingManager.getInstance().getCurrentTool()).getName());
FrameMain.jPanel6.repaint();
}
} catch (Interr`enter code here`uptedException ex) {
Logger.getLogger(TestAction.class.getName()).log(Level.SEVERE, null, ex);
} catch (ExecutionException ex) {
Logger.getLogger(TestAction.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
And this is where am calling TestAction:
if (!WorkFlow.isIsWorkflow()) {
SwingUtilities.invokeLater(
new Runnable() {
#Override
public void run() {
webServiceExecution();
}
});
} else {
new TestAction().execute();
}
running in a loop one after the other and notify UI when one is done
sounds like "big job with intermediate results". Intermediate results are supported via the publish/process methods:
implement doInBackground to loop through the jobs and call publish when one is terminated
implement process to do the ui update
you can use Thread.currentThread().sleep(5000); in SwingWorker's doInBackground method before currentthread finishes its execution and update your UI
You could add a Runnable to your constructor to be run when done() is over:
public class TestAction extends SwingWorker<Boolean, Void> {
boolean executeThread = false;
private final Runnable runWhenDone;
public TestAction(Runnable runWhenDone) {
this.runWhenDone = runWhenDone;
}
//...
#Override
protected void done() {
try {
boolean isOver = (boolean) get();
if (isOver) {
MainApplication.getInstance().getFrame().setStatus(LangUtil.getString("cdsExecuteFinehed")
+ " " + ((WebServiceTool) DrawingManager.getInstance().getCurrentTool()).getName());
//Run the Runnable here
runWhenDone.run();
//...
And in your GUI class
Runnable r = new Runnable() {public void run() {updateTheTitle();}};
(new TestAction(r)).execute();
private void updateTheTitle() { yourTitle.setText("I am done");}