When I click on a button, another button should be clicked programmatically after 2 seconds.
Helper.setTimeout(() -> {
_view.findViewById(R.id.turbineStandBy).performClick();
}, 2000);
When I run this code, I get this exception:
Only the original thread that created a view hierarchy can touch its
views.
public static void setTimeout(Runnable runnable, int delay){
new Thread(() -> {
try {
Thread.sleep(delay);
runnable.run();
}
catch (Exception e){
System.err.println(e);
}
}).start();
}
I think that I have to override the method run() but how can I do that in my setTimeout() method?
Only the original thread that created a view hierarchy can touch its
views.
The exception tells you that you must run the Runnable in the main thread. To do so, you can use Looper.getMainLooper or Activity#runOnUIThread (cf. runOnUiThread vs Looper.getMainLooper().post in Android).
Below codes are structural examples (you might still need to make somewhat modification).
Using Looper.getMainLooper:
public void setTimeout(Runnable runnable, int delay) {
new Handler(Looper.getMainLooper()).postDelayed(runnable, delay);
}
Using Activity#runOnUIThread:
public void setTimeout(Activity activity, Runnable runnable, int delay) {
new Thread(() -> {
try {
Thread.sleep(delay);
activity.runOnUIThread(runnable);
}
catch (Exception e){
System.err.println(e);
}
}).start();
}
(Note: I don't know whether you should put static modifier to the method or not.)
Apparently, in your case you want to make delay, using Looper.getMainLooper combined with Handler#postDelayed looks smarter.
Just use post delayed method
button.setOnClickListener(view -> {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//click your button here
}
},2000);
});
Related
Need To Do One Animation, Sleep 1000 Then Do The Next Sleep 1000 And So On, Instead It Sleeps For The Entire Time Then Plays All Animations At Once. No Idea What Im Doing.
Tried Timers, Running The Animation Before The tread.sleep And Using A While Loop Instead Of A For.
private void playLaunchAnimation()
{
final Animation animation = AnimationUtils.loadAnimation(this, R.anim.fadein);
for(int i=0; i < buttons.size();i++)
{
try {
Thread.sleep(1000);
buttons.get(i).startAnimation(animation);
} catch (Exception e){
/*
main declares that it throws InterruptedException. This is an exception that sleep throws when another thread interrupts the current thread while sleep is active. Since this application has not defined another thread to cause the interrupt, it doesn't bother to catch InterruptedException.
*/
}
}
}
Hi, Make sure this code helps you
public static void main(String[] args) throws Exception {
for(int i=0; i < 10;i++) {
try {
Thread.sleep(1000);
System.out.println(i);
if(i==9) {
i=0;
}
} catch (Exception e){
System.out.println("error");
}
}
}
(Answer assumes Android which wasn't entirely clear in OP.)
This is somewhat of a lazy way to do it - but maybe get you thinking. It would
be more interesting to have the handler invoke the next handler so only one handler is declared - but that would be a little more work.
private void playLaunchAnimation() {
final Animation animation = AnimationUtils.loadAnimation(this, R.anim.fadein);
for(int i=0; i < buttons.size();i++)
{
// Create a handler on the UI thread to execute after a delay.
// The delay is a function of loop index.
//
// It may be necessary to declare buttons final - but your
// OP did not list where it is defined.
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
buttons.get(i).startAnimation(animation);
}
}, ((i+1)*1000));
}
}
References:
How to call a method after a delay in Android
Android basics: running code in the UI thread
It sounds like you are calling Thread.Sleep from the User Interface thread. This will ultimately result in the entire User Interface freezing up for the duration of the sleep. What you really want is to launch sleep from a background thread.
For example:
AsyncTask.execute(new Runnable() {
#Override
public void run() {
for(int i=0; i < buttons.size();i++)
{
try {
Thread.sleep(1000);
activity.runOnUiThread(new Runnable() {
buttons.get(i).startAnimation(animation);
});
} catch (Exception e){}
}
});
Another way you could do this using post delay:
new android.os.Handler().postDelayed(
new Runnable() {
public void run() {
buttons.get(i).startAnimation(animation);
new android.os.Handler().postDelayed(this, 1000);
}
},
1000);
I just had to write a test code for SWT threading test, and now stuck with Display.asyncExec() strange behavior.
addShellListener(new ShellAdapter() {
#Override
public void shellActivated(ShellEvent e) {
Display.getDefault().asyncExec(new Runnable(){
#Override
public void run() {
for(int i=0;i<1000;i++)
{
getLabel().setText(i+"");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
}
});
I just run loopped Runnable with asyncExec on shell start, which updates label value inside the shell every second, simulating timer. Everything is okay and ticking until i try to drag the window. The window freezes on dragging (including "ticking" label) and notification "The program is not responding" appears, with exiting possible only by Java VM process killing.
I am not quite sure if I understand the use case, however in order to update the label every second, I recommend to wither spawn a background thread that triggers the label update every second or use timerExec() to do the update and schedule another timerExec() for the next update():
timerExec() variant
private class LabelUpdater implements Runnable {
#Override
public void run() {
if( !label.isDisposed() ) {
label.setText( ... );
label.getParent().layout();
display.timerExec( 1000, new LabelUpdater() );
}
}
}
shell.addListener( SWT.Activate, new Listener() {
#Override
public void handleEvent( Event event ) {
display.timerExec( 1000, new LabelUpdater() );
}
} );
Background Thread Variant
private class LabelUpdater implements Runnable {
#Override
public void run() {
if( !label.isDisposed() ) {
label.setText( ... );
label.getParent().layout();
}
}
}
Runnable runnable = new Runnable() {
#Override
public void run() {
while( !shell.isDisposed() ) {
display.asyncExec( new LabelUpdater() );
try {
Thread.sleep( 1000 );
} catch( InterruptedException ignore ) {
Thread.interrupted();
}
}
}
};
Thread thread = new Thread( runnable );
thread.setDaemon( true );
thread.start();
Note that the shell.isDisposed() check isn't thread-safe, but doesn't harm in practice because the LabelUpdater has to check if the widgets it updates are still alive anyway. (see here for a more detailed discussion.
The Runnable you give to Display.asyncExec is run in the SWT user interface thread. If you use Thread.sleep in this runnable the whole user interface will be blocked for the duration of the sleep so do not do this.
Instead of the sleep you can use
Display.getDefault().timerExec(1000, runnable);
to schedule a new runnable to be run 1000 milliseconds later.
In my GUI I have a PDF file creation operation. The operation can take up to 10-15 seconds to complete. When I start the operation, I attach a listener to it. The listener changes the cursor and disables the GUI, until the operation completes.
I would also like to add a progressbar, so the users will have a idea when it is going to complete.
Created a method startProgressBar() and called it from the start of the operation method.
See Below:
private void startSavePdfOperation() {
startProgressBar();
saveOp = new AplotSaveOperation(appReg.getString("aplot.message.SAVETOPDF"), "PDF", session);
saveOp.addOperationListener(new MyOperationListener(this) {
startProgressBar Method - See Below:
public void startProgressBar() {
Shell shell = new Shell(getShell());
shell.setSize(260, 120);
final ProgressBar bar = new ProgressBar(shell, SWT.SMOOTH);
bar.setBounds (20, 20, 200, 20);
shell.open();
final int maximum = bar.getMaximum();
new Thread(new Runnable() {
public void run() {
for (final int[] i = new int[1]; i[0] <= maximum; i[0]++) {
try {Thread.sleep (100);} catch (Throwable th) {}
if (Display.getDefault().isDisposed()) return;
Display.getDefault().asyncExec(new Runnable() {
public void run() {
if (bar.isDisposed ()) return;
bar.setSelection(i[0]);
}
});
}
}
}).start();
The code above created the ProgressBar. The issue is that the operation would end well before the progressbar indicator was close to ending.
Question: Is this because in the method I am creating a new thread and the indicator is updating according to the new thread and not the operation thread?
Question: Is it possible to create a new thread that watches the GUI thread and updates the progressbar accordingly?
Read a article suggesting using ProgressMonitorDialog with IRunnableWithProgress.
Method startProgressBar using ProgressMonitorDialog - see below:
public void startProgressBar() {
ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell());
try {
dialog.run(true, true, new IRunnableWithProgress(){
public void run(IProgressMonitor monitor) {
monitor.beginTask("Some nice progress message here ...", 100);
** getThread(); **
monitor.done();
}
});
}
catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void getThread() {
new Thread etc.. etc...
}
It seems that it will have the same issues with threading and updating as the code above.
Question: So now I am thinking can I just add or update the ProgressBar to my existing Listener
OperationListener Code - see below:
public abstract class MyOperationListener implements InterfaceAIFOperationListener {
AplotCreatePDFDialog w = null;
public MyOperationListener(AplotCreatePDFDialog win) {
w = win;
}
public void startOperation(String startMessage) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
w.getShell().setCursor(new Cursor(Display.getCurrent(), SWT.CURSOR_WAIT));
w.recursiveSetEnabled(getShell(), getShell().getEnabled());
w.getShell().setEnabled(!getShell().getEnabled());
}
});
}
public void endOperation() {
try {
endOperationImpl();
}
finally {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
w.getShell().setCursor(new Cursor(Display.getCurrent(), SWT.CURSOR_ARROW));
w.recursiveSetEnabled(getShell(), true);
w.getShell().setEnabled(!getShell().getEnabled());
w.close();
}
});
}
}
abstract protected void endOperationImpl();
} // end class MyOperationListener
Thanks for any help you can give me with this.
EDIT
Baz, your answer below is exactly what the question asked, so thank you for answering.
But I am starting to think that what I am trying to do is not possible.
When my operation starts, I wanted the progress bar indicator to start and when my operation ended I wanted the indicator be at the end and the monitor would close.
I thought there might bee a way to use my listener to add the progressbar. Something like the following.
public void startOperation(String startMessage) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
->monitor.beginTask("Creating PDF File(s)", IProgressMonitor.UNKNOWN);<-
w.getShell().setCursor(new Cursor(Display.getCurrent(), SWT.CURSOR_WAIT));
w.recursiveSetEnabled(getShell(), getShell().getEnabled());
w.getShell().setEnabled(!getShell().getEnabled());
}
});
}
public void endOperation() {
try {
->monitor.worked(1);<-
endOperationImpl();
}
finally {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
w.getShell().setCursor(new Cursor(Display.getCurrent(), SWT.CURSOR_ARROW));
w.recursiveSetEnabled(getShell(), true);
w.getShell().setEnabled(!getShell().getEnabled());
->monitor.done();<-
w.close();
}
});
}
}
abstract protected void endOperationImpl();
} // end class MyOperationListener
But I am starting to see that the ProgressBar has to have some sort of measurement to display the indicator correctly.
I would be happy if the indicator just went back and forth and the monitor would close at the end of the operation.
Why not use ProgressMonitorDialog?
Here is a related answer from me showing a simple example.
This is what it looks like:
If you are not sure about the workload, use this code:
monitor.beginTask("Copying files", IProgressMonitor.UNKNOWN);
It will show the idle bar while running.
In the following lines of code when Button1 is pressed the Jframe becomes unresponsive till the execution of the encode() method is completed. But I need to update a progress bar in the Jframe displaying the progress.
private void Button1ActionPerformed(java.awt.event.ActionEvent evt) {
try {
if (flagState == 0) {
WavFile.decode(readWavFile, msg.getText(), key.getText().hashCode());
} else if (flagState == 1) {
WavFile.encode(readWavFile, msg.getText(), key.getText().hashCode());
}
} catch (WavFileException | IOException e) {
notes.setText(e.getMessage());
}
}
I thought of doing this
private void Button1ActionPerformed(java.awt.event.ActionEvent evt) {
try {
if (flagState == 0) {
Thread t = new Thread(new Runnable() {
public void run() {
WavFile.decode(readWavFile, msg.getText(), key.getText().hashCode());
}
};)
t.start();
} else if (flagState == 1) {
Thread t = new Thread(new Runnable() {
public void run() {
WavFile.encode(readWavFile, msg.getText(), key.getText().hashCode());
}
};)
t.start();
}
} catch (WavFileException | IOException e) {
notes.setText(e.getMessage());
}
}
and update the progress bar from the encode() method.
But I understand that it will a strong coupling between the modules and i dont want that.
I also dont think that calling a new thread every time is a good idea ( thought of ExecutorService but not sure how to use it).
What should I do to make this into a decent piece code??
Threading is definitely something you have to introduce here. Anything that takes a significant amount of time to complete should not be run in the awt event thread.
Spawning a new thread each time the button is clicked is not inherently a problem. You should consider, though, that it may be possible to spawn many threads doing the same thing before even the first completes. You could use an Executor if you want, but it probably is not necessary.
As for tracking progress, I would add another thread that periodically queries the other thread and updates the progress bar as necessary. Here's how I would structure it:
private void Button1ActionPerformed(java.awt.event.ActionEvent evt) {
disableButton1();
final Thread t;
if (flagState == 0) {
t = new Thread(new Runnable() {
public void run() {
try {
WavFile.decode(readWavFile, msg.getText(), key.getText().hashCode());
} catch (WavFileException | IOException e) {
notes.setText(e.getMessage());
}
}
});
} else if (flagState == 1) {
t = new Thread(new Runnable() {
public void run() {
try {
WavFile.encode(readWavFile, msg.getText(), key.getText().hashCode());
} catch (WavFileException | IOException e) {
notes.setText(e.getMessage());
}
}
});
}
Thread monitor = new Thread(new Runnable() {
public void run() {
try {
while (notComplete(t)) {
setProgressBar(getProgress(t));
Thread.sleep(SLEEP_TIME);
}
t.join();
} finally {
enableButton1();
}
}
});
t.start();
monitor.start();
}
n the following lines of code when Button1 is pressed the Jframe becomes unresponsive till the execution of the encode() method is completed. But I need to update a progress bar in the Jframe displaying the progress.
you have issue with Concurency in Swing, you block the EDT, caused unresponsive GUI, until code ended
have look at SwingWorker for JProgressBar
use most scallable Swing Action instread of ActionListener
use implemented setEnabled() instead of if (flagState == 0) {
Multithreading is what you need, there is no other nice way i can think of don't worry about calling new threads, that's what they are there for, jvm has a thread pool ready to be used, this sort of things runs really good with threads, try it out!
Create a class that extends Runnable, implement the run method or make it call your current method, that should be enough to do this.
Also you could just make it sleep for a short time and check the status each time the sleep time goes out, if the process finished you can continue, if not, back to sleep for another short time, that way you don't have to ask that many times.
I hope it helps.
I have a problem following from my previous problem. I also have the code SwingUtillities.invokeAndWait somewhere else in the code base, but when I remove this the gui does not refresh. If I dont remove it the error I get is:
Exception in thread "AWT-EventQueue-0" java.lang.Error: Cannot call invokeAndWait from the event dispatcher thread
at java.awt.EventQueue.invokeAndWait(Unknown Source)
at javax.swing.SwingUtilities.invokeAndWait(Unknown Source)
at game.player.humanplayer.model.HumanPlayer.act(HumanPlayer.java:69)
The code in HumanPlayer.act is:
public Action act(final Action[] availiableActions) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
gui.update(availiableActions);
}
});
}
catch (InterruptedException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
synchronized(performedAction){
while(!hasPerformedAction()){
try {
performedAction.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
setPerformedAction(false);
}
return getActionPerfomed();
}
Image of threads when in debug as screen doesn't paint:
alt text http://img684.imageshack.us/img684/6669/69288941.png
Text version of stack:
ui.startup.LoginScreen at localhost:51050
-> Deamon Thread [AWT-Windows] (Running)
-> Thread [AWT-Shutdown] (Running)
-> Thread [AWT-EventQueue-0] (Running)
-> Thread [DestroyJavaVM] (Running)
The answer was instead of making the call
new GameInitializer(userName, player, Constants.BLIND_STRUCTURE_FILES.get(blindStructure), handState);
from the EDT, make it execute on a new (non EDT) thread so that later when invokeAndWait is called it functions as correctly as the thread running that command is not the EDT. The amended code is as follows:
Thread t = new Thread(new Runnable() {
#Override
public void run() {
new GameInitializer(userName, player, Constants.BLIND_STRUCTURE_FILES.get(blindStructure), handState);
}
});
t.start();
invokeAndWait() is meant to be called from the non-GUI thread. It sends a Runnable object to the GUI thread where it will be executed.
There's no point in sending a Runnable object from the GUI-thread to itself. It has the same effect as calling run() on the Runnable object directly.
You can check before if your current calling thread is already the event dispatcher:
private void syncExec(final Runnable r) {
try {
if (EventQueue.isDispatchThread()) r.run();
else EventQueue.invokeAndWait(r);
} catch (final Exception e) {
Throws.throwRuntime(e);
}
}
Note that SwingUtilities.invokeAndWait(Runnable) simply delegates to the EventQueue.
Based on the comments, it appears you are not repainting the frame once the actions are completed. If you do not, then the screen will only be updated at what seems to be random times (when another window moves in front, perhaps).
Inside gui.update, I suggest you make the last line:
myFrame.repaint();
(more or less, depending on your circumstances).
Edit: As it turns out, the actual problem is this loop:
synchronized(performedAction){
while(!hasPerformedAction()){
try {
performedAction.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
setPerformedAction(false);
}
Since there is only one application thread (which happens to be the EDT), the result of hasPerformedAction() can never change (assuming it's a simple getter). There is no other thread to change the value. Since this infinite loop is on the EDT, the GUI can never be repainted; hence it locks up.
When using XChart java library you can show your chart on button click with this code:
JButton btn = new JButton("View chart");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
new SwingWrapper(yourChart).displayChart();
}
});
t.start();
}
});
try to execute your code from this
Executors.newSingleThreadExecutor().execute(new Runnable() {
public void run() {
}
});