TimerTask can not update UI? - java

new Timer().schedule(new TimerTask() {
public void run() {
KeyBoardUtil.showKeyBoard(et_search);
}
}, 300);
I show the keyboard use TimerTask,and it runs fine.
how to explain it?

You can use runOnUiThread :
runOnUiThread(new Runnable(){
public void run() {
// Your code
}
});
Or
Handler mainHandler = new Handler(context.getMainLooper());
Runnable myRunnable = new Runnable() {
#Override
public void run() {
// Your code
}
};
mainHandler.post(myRunnable);
developer.android.com
In the previous lesson you learned how to start a task on a thread managed by ThreadPoolExecutor. This final lesson shows you how to send data from the task to objects running on the user interface (UI) thread. This feature allows your tasks to do background work and then move the results to UI elements such as bitmaps.
Every app has its own special thread that runs UI objects such as View objects; this thread is called the UI thread. Only objects running on the UI thread have access to other objects on that thread. Because tasks that you run on a thread from a thread pool aren't running on your UI thread, they don't have access to UI objects. To move data from a background thread to the UI thread, use a Handler that's running on the UI thread.

Related

Java SWT UI Thread freeze even if run in new Thread

I have a problem with a long running task.
After my dialog is shown I want to scan a ftp directory. This task takes some time so I need to run this task no in the UI thread.
My idea was
#Override
protected void postDialogOpen() {
// if invoked via menu button
if (!scanFtp) {
final Display display = Display.getDefault();
new Thread(new Runnable() {
#Override
public void run() {
//initProgressWaitViewer();
scanFtpServer();
//closeProgressWaitViewer();
display.syncExec(new Runnable() {
#Override
public void run() {
updateTree();
}
});
}
}).run();
}
}
But during the execution of scanFtpServer() my dialog is not movable and if I click on it it becomes "unresponsible".
Is there something I am doing wrong?
When calling method run() in class Thread, you are executing the method on the caller thread, just like calling any other method. If you want to spawn a new thread and execute method run() in that thread, you need to call method start() instead, that will do all the work of setting up the thread and running it.
So replace
}).run();
with
}).start();
Try to do .start() instead of .run() .

Updating buttons inside or outside of SwingWorker?

I want to disable a number of buttons/menu items of my GUI while a SwingWorker thread is running. The thread is started when a button is clicked.
It looks like the while loop in my code causes the CPU load to go up significantly. Did I get something wrong about how to determine if a SwingWorker thread is still running?
The CPU load's definitely lower when I update the buttons/menu items inside the SwingWorker thread. However, I felt like that shouldn't be the SwingWorker thread's job. Should it?
JButton button = new JButton("Start");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
menu.setEnabled(false);
MySwingWorker worker = new MySwingWorker();
worker.execute();
while (true) {
if (worker.isCancelled() || worker.isDone()) {
menu.setEnabled(true);
break;
}
}
}
});
t.start();
}
});
Swing GUI objects should be constructed and manipulated only on the event dispatch thread (EDT). Doing so from t is incorrect. As suggested in examples cited here, condition your GIU elements on the EDT before starting the worker, and update the GUI in process() or done().

How to refresh ProgressMonitor in Swing?

ProgressMonitor is designed to handle long operations, but if used directly, then it does not refresh.
Thread worker = new Thread() {
#Override
public void run() {
//Code, that's freezing your gui
}};
worker.start();

update TextView every second with ScheduledThreadPoolExecutor

I need tu update my TextView every second. I wrote it with Timer and TimeTask but everyone says its deprecated method.
Can someone show me how to make simple timer which updates TextView every 1 second with possibility stop it from UI?
You can use a handler or a count down timer
Handler m_handler;
Runnable m_handlerTask ;
m_handler = new Handler();
m_handlerTask = new Runnable()
{
#Override
public void run() {
// do something. update text view.
m_handler.postDelayed(m_handlerTask, 1000);
}
};
m_handlerTask.run();
To stop
m_handler.removeCallbacks(m_handlerTask);
Check this link for countdowntimer ,handler, timer
Android Thread for a timer
No need to create a separate Handler for this (as in the currently accepted answer). In stead, just postDelayed() the Runnable directly to the TextView's internal message queue:
Runnable runnable = new Runnable () {
#Override public void run() {
// do some work, then repost:
textview.postDelayed(runnable, 1000);
}
};
// post with an initial 1000 ms delay
textview.postDelayed(runnable, 1000);
// or post without an initial delay
textview.post(runnable);
// or even run the runnable right away the first time
runnable.run();
Alternatively, if all you're trying to accomplish is to 'redraw' the TextView, use invalidate() (or postInvalidate() from a non-UI thread). There are also overloads that allow you to restrict the invalidation to a specific rectangle, which you can potentially exploit for a more efficient implementation.
You could use a simple handler to do what you need to do. Anyway, with the scheduler way you could do:
private ScheduledExecutorService scheduler;
...
if(scheduler != null)
{
scheduler.shutdown();
scheduler = null;
}
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new Runnable()
{
public void run()
{
// do your stuff...
}
}, Consts.KEEP_ALIVE_TIMEOUT, Consts.KEEP_ALIVE_TIMEOUT, TimeUnit.MINUTES);

On click, Text of jLabel appears but not the Icon Image?

When I click Print Button it should show a Gif Animation followed by the text "Working..."
but here only the text "Working..." appears , not the animation.
Here's the Code:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
jLabel1.setVisible(true);
/* This portion is Time Consuming so I want to display a Loading gif animation. */
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
empPrint=new HashMap();
if(!empPrint.isEmpty())
empPrint.clear();
if(jRadioButton1.isSelected())
empPrint.put("PNO",parent.emp.getPAN());
else
empPrint.put("PNO",records.get(jComboBox1.getSelectedItem()));
REPORT="Report.jrxml";
try {
JASP_REP =JasperCompileManager.compileReport(REPORT);
JASP_PRINT=JasperFillManager.fillReport(JASP_REP,empPrint,parent.di.con);
JASP_VIEW=new JasperViewer(JASP_PRINT,false);
JASP_VIEW.setVisible(true);
JASP_VIEW.toFront();
}
catch (JRException excp) {
}
setVisible(false);
}
});
}
You should use a SwingWorker for time consuming tasks. Using invokeLater() just pushes it to the event queue, and it gets run in the EDT, blocking it.
Drawing in swing is done in the event dispatch thread, but since the EDT is busy running your printing task, swing has no chance to process repaint requests.
// Note the upped case "Void"s
SwingWorker worker = new SwingWorker<Void, Void>() {
#Override
public Void doInBackground() {
// Do the printing task here
return null;
}
#Override
public void done() {
// Update the UI to show the task is completed
}
}.execute();
The SwingUtilities.invokeLater() method will not help you in this case. The Runnable you pass still gets executed on the Event Dispatch Thread (EDT, the thread responsible for drawing the UI and responding to clicks etc.).
You could look at SwingWorkers, but you could just as well use a simple ExecutorService and pass the Runnable to there. The Executor framework - which was added in Java 5 or 6 - offers relatively simple to use tools to have stuff run in the background without having to worry about your own threads. I recommend going with something like this (pseudo code):
private ExecutorService executor = Executors.newFixedExecutorService()
....
public void buttonPressed() {
label.setVisible(true);
...
executor.submit(new Runnable() {
// create the report etc.
// DO NOT ACCESS ANY UI COMPONENTS FROM HERE ANYMORE!
// ...
SwingUtilities.invokeLater(new Runnable() {
// update the UI in here
label.setVisible(false);
});
});
}
As you can see, SwingUtilities.invokeLater is used here, too. However, it is called from a background thread to make sure your UI code gets executed on the EDT instead of on the background thread. That is what it is designed for, because UI components must never be accessed (not even read from!) from a background thread. That way you have a convenient mechanism to update you label nevertheless. You could also use it to update some progress bar etc.

Categories