JTextfield looping text issue - java

I have created a GUI using swings package containing a button and a text field, and have also added event handling on button such that when it gets clicked, the textfield should display a message continuously for 5 times as it is in loop.
public void actionPerformed(ActionEvent ae){
for(int i=0;i<5;i++){
tx.setText("Running"+i);// here tx is the JTextField object
}

if you wish to show it as an animation, you have to do it at background or another thread.
here is a sample
private Task task;
private void ButtonActionPerformed(java.awt.event.ActionEvent evt)
{
task = new Task();
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
task.execute();
}
class Task extends SwingWorker<Void, Void>
{
#Override
public Void doInBackground() throws Exception
{
for(int i=0;i<5;i++)
{
Lab.setText("Running"+i);
Thread.sleep(200);
}
return null;
}
}

Use Runnable and put thread inside it..
Runnable run = new Runnable() {
#Override
public void run() {
for(int i=0 ; i<5;i++){
try {
Thread.sleep(1000); //time to wait
jTextField_Cost.setText("Running"+i+"");
}catch(InterruptedException e1){
e1.printStackTrace();
}
}
}
};
ExecutorService _ex = Executors.newCachedThreadPool();
_ex.execute(run);
You can also use
new Thread(run).start();
But ExecutorService is useful when we are using large number of thread in program.. have a look at this post

Related

How to pause a thread using wait and notify JavaFX

I am unclear on how to use wait() and notify() to pause a thread. I read talk about synchronizing, but I'm unsure how to do it in my instance. I have a music player with a progress bar where I want to pause the thread in control of syncing the progress bar with the music. Here is the thread I want to pause:
#FXML private void clickedButton(ActionEvent event){
shuffle.setOnAction(e -> {
artistPane.setText(model.getCurrentSong());
if(firstTime){
//Multithreading with JavaFX. Essentially this other thread will check the slider to make sure its on track.
sliderThread = new Task<Void>() {
#Override
protected Void call() throws Exception {
boolean fxApplicationThread = Platform.isFxApplicationThread();
System.out.println("Is call on FXApplicationThread: " + fxApplicationThread);
//this is an infinite loop because now I only need to make this thread once, pausing and starting it, as opposed to making many threads
for(;;){
Thread.sleep(100);
progressBar.setValue(controller.getPercentageDone());
}
}
};
new Thread(sliderThread).start();
firstTime = false;
}else if(!model.getIsPlaying()){
//I want to start the thread here
}
controller.shuffle(); //this will start the music on the next song
});
Here is the second half where I also want to pause and start the thread:
play.setOnAction(e -> {
controller.play(); //this will pause/start the music
if(!model.getIsPlaying()){
//where I want to pause the thread.
}else{
//I want to start the thread here
}
});
I will try to give you simple example and you try to apply it to your program...
public class TestClass extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
private Thread playThread ;
TestClass() {
playThread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("DO SOME THING HERE");
System.out.println("SONG WILL PLAY.....");
}
});
}
public void startMyPlayer() {
System.out.println("PLAYING NOW...");
playThread.start();
}
public void pauseMyPlayer() throws InterruptedException {
System.out.println("PAUSED NOW...");
playThread.wait();
}
public void resumeMyPlayer() {
System.out.println("RESUMING NOW...");
playThread.notify();
}
}
That's it.I hope this help you.

Calling a method from ActionPerformed and running it on main thread

my program's UI freezes for some time after pressing a JButton. I discovered that a cause of this is a Semaphore clogging the Swing thread. This is the method containing the acquire() call on the Semaphore:
private void fetch(int numThreads) {
//some code here
sem = new Semaphore(numThreads);
for (int i = 0; i < model.getRowCount(); i++){
try {
sem.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
//some code here
}
And here is the only method that makes a call to fetch()
concFetchButt.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
switchButtonStates(false);
}
});
fetch(Integer.parseInt(threadsNumField.getText()));
}
As I understand, this code ends up running fetch() on the Swing thread, though, supposedly it has nothing to do with Swing.
I guess, my question is this: How do I run a method called from 'ActionPerformed()' of Swing on the main thread of the program instead of the Swing thread?
No need to specifically run that on the "main" thread. Simply run it on any other thread but the Swing UI thread.
The most simple solution to get there:
add an ExecutorService to your class
put that code fetch(Integer.parseInt(threadsNumField.getText())); into a Runnable object
Submit that Runnable to the ExecutorService
Along the lines of:
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(new Runnable() {
public void run() {
fetch(Integer.parseInt(threadsNumField.getText()));
}
});

What to use to create search engine using onKeyReleased event

I am trying to create a search bar which will search the entered string or character from db. While first character is typed in textfield it should wait for next 200ms, if next character is entered within that time then it will restart the counter and again wait for next 200ms if not, then it will search from db.
Here is some code which i tried but not work for me
#FXML protected void keyReleased(KeyEvent evt)throws Exception {
if (evt.getCode() != KeyCode.BACK_SPACE) {
String ch = evt.getText();
String[] myArray = new String[5];
run();
searchFrmDb(ch, myArray);
}
}
public void run(){
for(int i=1;i<5;i++){
try{
Thread.sleep(200);
}catch(InterruptedException e){System.out.println(e);}
System.out.println(i);
}
}
public void searchFrmDb(String ch,String[] myArray){
//db search operation ...
}
I am new in java help me out to sort out my problem
What should i use thread or Timer or anything else
Consider using a PauseTransition for functionality like this.
public class ControllerClass {
private final PauseTransition pauseBeforeSearch = new PauseTransition(Duration.millis(200));
#FXML protected void keyReleased(KeyEvent evt)throws Exception {
if (evt.getCode() != KeyCode.BACK_SPACE) {
pauseBeforeSearch.setOnFinished(e -> {
searchFrmDb(evt.getText(), new String[5]);
});
pauseBeforeSearch.playFromStart();
}
}
}
I would have a look at java.util.Timer and java.util.TimerTask:
class SearchTimerTask extends TimerTask{
#Override
public void run(){
searchFrmDb();
}
#Override
public void cancel(){
super.cancel();
//handle cancellation logic if necessary
}
}
Keep a reference to a Timer and a TimerTask somewhere:
Timer timer = new Timer();
TimerTask task;
Then in your key event handler you simply cancel the current task if there is one and fire up a new one:
#FXML protected void keyReleased(KeyEvent evt)throws Exception {
if (evt.getCode() != KeyCode.BACK_SPACE) {
if(task != null){
task.cancel();
task = new SearchTimerTask();
}
timer.schedule(task, 200);
}
}

How to know when two threads are finished in Swing

I have to perform two tasks. I like two threads perform each task simultaneously. The tasks don't share data.
Before the tasks start, is shown a dialog with a info "Wait, processing...".
Here the codes:
final JDialog dialog = new JDialog(this, true);
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
// Do the job
return null;
}
#Override
protected void done() {
// Must close dialog? The other finished?
}
};
SwingWorker<Void, Void> worker2 = new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
// Do the job
return null;
}
#Override
protected void done() {
// Must close dialog? The other finished?
}
};
worker.execute();
worker2.execute();
dialog.setVisible(true);
// Must close dialog?
I would like to close the dialog only when the two threads ended. How to know when they ended? Who and when should close the dialog?
Update: the threads must run simultaneously, not in sequential mode.
Create a CountDownLatch, set to 2
Create your two SwingWorkers, passing each a reference to the CountDownLatch. In there done methods, call countDown on the latch. Do this in the done method, as it will be called regardless of how the doInBackground method exited (ie in case it throws an Exception)
Create a third SwingWorker, passing it a reference to the CountDownLatch, in this worker wait for the latch in the doInBackground method. Once this SwingWorker's done method is called, you should now be able to dispose of the dialog safely
You should call get() on both workers
For now I have made a sample code which will help you to understand the logic behind this.
import java.awt.BorderLayout;
import javax.swing.*;
public class DemoTest {
JFrame frame = new JFrame();
JLabel lbl1 = new JLabel();
JLabel lbl2 = new JLabel();
SwingWorker<Void,Void> worker1 = new SwingWorker<Void,Void>()
{
#Override
protected Void doInBackground() throws Exception {
for(int i = 0;i<=100;i++)
{
lbl1.setText("Counter1 Value:"+Integer.toString(i));
try
{
Thread.sleep(100);
}
catch(Exception e)
{
e.printStackTrace();
}
}
return null;
}
#Override
protected void done()
{
lbl1.setText("Thread 1 completed its job");
worker2.execute();
}
};
SwingWorker<Void,Void> worker2 = new SwingWorker<Void,Void>()
{
#Override
protected Void doInBackground() throws Exception {
for(int i = 0;i<=100;i++)
{
lbl2.setText("Counter1 Value:"+Integer.toString(i));
try
{
Thread.sleep(100);
}
catch(Exception e)
{
e.printStackTrace();
}
}
return null;
}
#Override
protected void done()
{
lbl2.setText("Thread 2 completed its job");
}
};
public DemoTest()
{
frame.setSize(400,400);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(lbl1,BorderLayout.NORTH);
frame.add(lbl2,BorderLayout.SOUTH);
frame.setVisible(true);
try
{
worker1.execute();
}
catch(Exception e)
{
e.printStackTrace();
}
//close dialog box
}
public static void main(String []args)
{
DemoTest d = new DemoTest();
}
}
I would use something like a counting lock for this. It is definitely using the least possible resources. The class below is a counting lock. Basically you initialise it with the constructor and specify the number of threads you need to wait for.
In the main thread (or UI thread) you call "waitForAll()" once you are done with setup. You can see that waitForAll is basically waiting for a notify from any other thread. If a notify is received it checks whether or not the number of active workers has reached zero. If the number of active workers is still greater 0 it waits again.
The workers however call unlock() on the lock. Notify decreases the counter by one and calls notify() which makes the main thread wake up and perform the above mentioned procedure.
public class CountingLock {
private int counter;
/**
* Number of workers
*
* #param n
*/
public CountingLock(int n) {
this.counter = n;
}
/**
* Wait until counter == 0
* #throws InterruptedException
*/
public synchronized void waitForAll() throws InterruptedException {
while(counter > 0) {
this.wait();
}
}
/**
* Deduce counter and notify
*/
public synchronized void unlock() {
this.counter--;
this.notify();
}
}
In the dialog prior launching the threads do the following:
CountingLock lock = new CountingLock(2);
/** put your thread setup code from your example here */
lock.waitForAll();
dialog.setVisible(false);
Make sure to pass a reference of lock to your threads and at the end of each thread call the following:
lock.unlock();
As per the comment to this answer, Java as of Java 1.5 (verified) provides a class java.concurrent.CountDownLatch with the exactly same behaviour. The use is well documented in the API.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html
example with CoundDownLatch
CountDownLatch lock = new CountDownLatch(2);
/** put your thread setup code from your example here */
lock.await();
dialog.setVisible(false);
In the threads do the following:
lock.countDown();
full example
final CountingLock lock = new CountingLock(2);
final JDialog dialog = new JDialog(this, true);
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
// Do the job
return null;
}
#Override
protected void done() {
// Must close dialog? The other finished?
lock.unlock();
}
};
SwingWorker<Void, Void> worker2 = new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
// Do the job
return null;
}
#Override
protected void done() {
// Must close dialog? The other finished?
lock.unlock();
}
};
worker.execute();
worker2.execute();
dialog.setVisible(true);
lock.waitForAll();
dialog.setVisible(false);
Actually you should also consider to move the waitForAll or await call and setting dialog.setVisible(false) in another background thread since you most likely will not want the UI to stall.

Waiting for thread while updating Swing

I have problem with handling threads in my application. It creates JFrame and starts a new Thread. Last one will execute external application and update GUI. Then
I have problem to make Main class to wait for second thread to finish, but also to update GUI simultaneously.
Here's my example (shortened):
class Main {
public int status;
public Main() {
// Creating GUI etc.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JDialog id = new JDialog();
id.button.addMouseListener(new MouseListener()); // Calls generate() method
}
});
}
public void generate() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// Make changes to GUI
}
});
GeneratorThread genTest = new GeneratorThread(this, 1, 1, 1);
genTest.start();
//while (status == 0);
System.out.println("Next step.");
}
}
And Thread class:
public class GeneratorThread extends Thread {
protected Main main;
protected int setSize, minValue, maxValue;
public GeneratorThread(Main main, int setSize, int minValue, int maxValue) {
this.main = main;
this.setSize = setSize;
this.minValue = minValue;
this.maxValue = maxValue;
}
public void run() {
// Execute program etc.
// Change GUI from main in the same time
// About 3 seconds
main.status = 1;
}
}
I'm in progress and I wanted to check how it works so far. While worked nice, but it locks Swing somehow and any changes are visible only when GeneratorThread finishes. I would like to update GUI in the real time.
I've tried join(), effects are the same. I also tried wait() (on Main), but then I got IllegalStateMonitorException.
Any hints?
Swing is a single threaded environment. That is, there is a single thread responsible for managing all the interactions and updates to the Swing UI - the Event Dispatching Thread.
Among the golden rules of Swing are...
DON'T block the EDT (Thread.sleep, Thread#join, Object#wait, block IO and/or time consuming tasks (among others) should never be called from within the EDT), doing so will stop the EDT from dispatching events and paint updates (amongst other things)
ONLY create/update Swing UI elements from within the EDT.
This raises a question...how do you "wait" for a thread?
The best way is use an Observer pattern. Basically, you provide the Thread with some kind of reference that it will call to provide notification of events, such as errors and completion...
This will require you to think very carefully about the design of your applications, as you can not rely on a simple A to B execution of your code.
For example...
public class TestThreadCallBack {
public static void main(String[] args) {
new TestThreadCallBack();
}
public TestThreadCallBack() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface ThreadCallBack {
public void threadCompleted(Runnable source);
public void threadFailed(Runnable source);
}
public class TestPane extends JPanel implements ThreadCallBack {
private JLabel message;
private JLabel dots;
private int count;
private Timer timer;
public TestPane() {
setLayout(new GridBagLayout());
message = new JLabel("Running background task, please wait");
dots = new JLabel(" ");
add(message);
add(dots);
timer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
count++;
if (count > 3) {
count = 0;
}
StringBuilder sb = new StringBuilder(3);
for (int index = 0; index < count; index++) {
sb.append(".");
}
for (int index = count; index < 3; index++) {
sb.append(" ");
}
dots.setText(sb.toString());
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
Thread thread = new Thread(new BackgroundTask(this));
thread.start();
}
#Override
public void threadCompleted(Runnable source) {
timer.stop();
message.setText("Task completed successfully");
}
#Override
public void threadFailed(Runnable source) {
timer.stop();
message.setText("Task failed");
}
}
public class BackgroundTask implements Runnable {
private ThreadCallBack callBack;
public BackgroundTask(ThreadCallBack callBack) {
this.callBack = callBack;
}
#Override
public void run() {
System.out.println("Background task underway...");
try {
Thread.sleep(2000);
} catch (InterruptedException interruptedException) {
}
int result = (int) Math.round((Math.random() * 1));
if (result == 0) {
callBack.threadCompleted(this);
} else {
callBack.threadFailed(this);
}
}
}
}
Updating the UI from within a Thread other then the EDT is, well, messy. An easier solution would actually be to use a SwingWorker. This has publish/process methods that make easy to update the UI and progress methods that can be used to provide feedback about the progress of the current task.
You can use it's done method to notify interested parties when the worker has completed.
Update your GUI from within the thread using SwingUtilitied.invokeLater or, alternatively, synchronise the main variable!
http://www.vogella.com/articles/JavaConcurrency/article.html#concurrencyjava
Maybe it already suffices to make "status" volatile?

Categories

Resources