hi id like to know whats the best way to add text to a jtextarea from a swingworkerthread, ive created another class which a jbutton calls by Threadsclass().execute();
and the thread runs in parallel fine with this code
public class Threadsclass extends SwingWorker<Object, Object> {
#Override
protected Object doInBackground() throws Exception {
for(int x = 0; x< 10;x++)
try {
System.out.println("sleep number :"+ x);
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(eftcespbillpaymentsThreads.class.getName()).log(Level.SEVERE, null, ex);
}
throw new UnsupportedOperationException("Not supported yet.");
}
}
now what id like to do is add the value of x to the text area on the main gui, any ideas much appreciated.
There is an excellent example from the JavaDocs
class PrimeNumbersTask extends
SwingWorker<List<Integer>, Integer> {
PrimeNumbersTask(JTextArea textArea, int numbersToFind) {
//initialize
}
#Override
public List<Integer> doInBackground() {
List<Integer> numbers = new ArrayList<Integer>(25);
while (!enough && !isCancelled()) {
number = nextPrimeNumber();
numbers.add(number);
publish(number);
setProgress(100 * numbers.size() / numbersToFind);
}
return numbers;
}
#Override
protected void process(List<Integer> chunks) {
for (int number : chunks) {
textArea.append(number + "\n");
}
}
}
JTextArea textArea = new JTextArea();
final JProgressBar progressBar = new JProgressBar(0, 100);
PrimeNumbersTask task = new PrimeNumbersTask(textArea, N);
task.addPropertyChangeListener(
new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
progressBar.setValue((Integer)evt.getNewValue());
}
}
});
task.execute();
System.out.println(task.get()); //prints all prime numbers we have got
Take a look at publish and process
The underlying intention is that you need to update the UI from only within the Event Dispatching Thread, by passing the data you want to updated to the UI via the publish method, SwingWorker will call process for you within the context of the EDT
Within doInBackground(), use publish(V... chunks) to send data to process(List<V> chunks).
See How SwingWorker works.
Related
I have a method like below.
ProgressWindow is a sub class of JFrame containing JProgressBar.
addProgress() increments a value in the JProgressBar.
If I call this method from a method in another class, a frame of ProgressWindow will show up but not JProgressBar and some JLabels inside the frame. They show up after the last line (System.out.println("finish")).
If I call this method in a main method in the class containing this method, then every component (Bar, labels...) instantly shows up.
What can I do for showing the window correctly?
static void search(){
ProgressWindow window = new ProgressWindow();
window.setVisible(true);
ExecutorService execs = Executors.newFixedThreadPool(Runtime
.getRuntime().availableProcessors());
Collection<Callable<Void>> processes = new LinkedList<>();
for (int i = 0; i < 100; i++) {
processes.add(new Callable<Void>() {
#Override
public Void call() throws Exception {
progressWindow.addProgress(); // increment progress value
return null;
}
});
}
try {
execs.invokeAll(processes);
} catch (Exception e) {
e.printStackTrace();
} finally {
execs.shutdown();
}
System.out.println("finish");
The main problem is you seem to be calling search from the context of the Event Dispatching Thread.
The problem occurs because you are using execs.invokeAll which blocks until all the callables have finished running.
This means that the EDT is unable to process new events in Event Queue, including repaint events, this is why your UI is coming to a stand still...
There are a number of issues you are now going to face...
You should never update/modify a UI component from any thread other than the EDT
You should block the EDT for any reason
You seem to want to know when the search is complete, so you know need some kind of event notification...
The first thing we need is some way to be notified that the search has completed, this means you can no longer rely on search returning when the search is complete...
public interface SearchListener {
public void searchCompleted();
}
Next we need an intermeditate search method that builds the UI and ensure that the search is launched within it's own Thread...
static void search(final SearchListener listener) {
final ProgressWindow window = new ProgressWindow();
window.setVisible(true);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
search(listener, window);
}
});
t.start();
}
Then we need to modify the original search method to utilise the SearchListener interface to provide notification when the search is complete...
static void search(final SearchListener listener, final ProgressWindow window){
ExecutorService execs = Executors.newFixedThreadPool(Runtime
.getRuntime().availableProcessors());
Collection<Callable<Void>> processes = new LinkedList<>();
for (int i = 0; i < 100; i++) {
processes.add(new Callable<Void>() {
#Override
public Void call() throws Exception {
// This method needs to ensure that
// what ever it does to the UI, it is done from within
// the context of the EDT!!
progressWindow.addProgress();
return null;
}
});
}
try {
execs.invokeAll(processes);
} catch (Exception e) {
e.printStackTrace();
} finally {
execs.shutdown();
}
System.out.println("finish");
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
listener.searchCompleted();
}
});
}
Now, without the source code for addProgress, I might be tempted to use
processes.add(new Callable<Void>() {
#Override
public Void call() throws Exception {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
progressWindow.addProgress();
}
});
return null;
}
});
}
Instead...
Take a look at Concurrency in Swing for more details
Sounds like you what you're wanting to do is invoke the setVisible on the Swing UI thread, you can do this with invokeAndWait or invokeLater.
So something like:
final ProgressWindow window = new ProgressWindow();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
window.setVisible(true);
}
});
So my JProgressBar I have set up doesn't work the way I want it. So whenever I run the program it just goes from 0 to 100 instantly. I tried using a ProgressMonitor, a Task, and tried a SwingWorker but nothing I tried works.
Here is my program:
int max = 10;
for (int i = 0; i <= max; i++) {
final int progress = (int)Math.round(
100.0 * ((double)i / (double)max)
);
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(BandListGenerator.class.getName()).log(Level.SEVERE, null, ex);
}
jProgressBar2.setValue(progress);
}
});
}
#MadProgrammer Here is my attempt at making a swing worker and writing each name to the document and updating the progress bar. The program gets to around 86 percent and stops, never creating the finished document. The program creates a blank document. Here are the two methods first is the SwingWorker object I made:
public class GreenWorker extends SwingWorker<Object, Object> {
#Override
protected Object doInBackground() throws Exception {
int max = greenList.size();
XWPFParagraph tmpParagraph;
XWPFRun tmpRun;
FileInputStream file =
new FileInputStream(location + "GreenBandList.docx");
gDocument = new XWPFDocument(OPCPackage.open(file));
for (int i = 0; i < max; i++) {
tmpParagraph = gDocument.getParagraphs().get(0);
tmpRun = tmpParagraph.createRun();
if (greenList.get(i).length() == 1) {
tmpRun.setBold(true);
tmpRun.setText(greenList.get(i));
tmpRun.setBold(false);
} else {
tmpRun.setText(greenList.get(i));//Write the names to the Word Doc
}
int progress = Math.round(((float) i / max) * 100f);
setProgress(progress);
}
return null;
}
}
And here is the code for the button that starts it and has my property change event.
private void GenerateGreenList() throws IOException, InterruptedException {
//Need to fix the bug that removes the Letter Header in Yellow Band list
//********************************************************************\\
//Delete the old list and make a new one
File templateFile = new File(location + "\\backup\\GreenTemplate.docx");
FileUtils.deleteQuietly(new File(location + "GreenBandList.docx"));
FileUtils.copyFile(templateFile, new File(location +
"GreenBandList.docx"));
//Get the New Entries
String[] entries = jTextPane3.getText().split("\n");
for (String s : entries) {
if (s != null) {
greenList.add(s);
}
}
//Resort the list
Collections.sort(greenList);
//Write the names to the document
GreenWorker worker = new GreenWorker();
worker.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
jProgressBar2.setValue((Integer) evt.getNewValue());
}
}
});
worker.execute();
if (worker.isDone()) {
try {
gDocument.write(new FileOutputStream(new File(location + "GreenBandList.docx")));
////////////////////////////////////////////////////////////
} catch (IOException ex) {
Logger.getLogger(BandListGenerator.class.getName()).log(Level.SEVERE, null, ex);
}
JOptionPane.showMessageDialog(null, "Green Band List Created!");
jProgressBar2.setValue(0);
}
}
I used the property change listener from one of your other posts but I don't really understand what the one you wrote does or what it does in general?
Swing is a single threaded environment, that is, there is a single thread which is responsible for processing all the events that occur within the system, including repaint events. Should anything block this thread for any reason, it will prevent Swing from processing any new events, including, repaint events...
So all this ...
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(BandListGenerator.class.getName()).log(Level.SEVERE, null, ex); }
jProgressBar2.setValue(progress);
}
});
Is constantly pausing the Event Dispatching Thread, preventing it from actually doing any updates (or at least spacing them randomly)...
It's also likely that your outer loop is been run from within the context of the EDT, meaning that until it exists, nothing in the Event Queue will be processed. All your repaint requests will be consolidated down to a single paint request and voila, instant filled progress bar...
You really should use a SwingWorker - I know you said you tried one, but you've not shown any code as to your attempt in this regards, so it's difficult to know why it didn't work, however...
SwingWorker and JProgressBar example
SwingWorker and JProgressBar example
SwingWorker and JProgressBar example
SwingWorker and JProgressBar example
SwingWorker and dual welding JProgressBar example
SwingWorker and JProgressBar example
And forgive me if we haven't said this a few times before :P
You are evoking Thread.sleep inside the EvokeLater which means that it is running on another thread than your for loop. i.e., your for loop is completing instantaneously (well, however long it takes to loop from 1 to 100, which is almost instantaneously).
Move Thread.sleep outside of EvokeLater and it should work as you intend.
int max = 10;
for (int i = 0; i <= max; i++) {
final int progress = (int)Math.round(
100.0 * ((double)i / (double)max)
);
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
jProgressBar2.setValue(progress);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(BandListGenerator.class.getName()).log(Level.SEVERE, null, ex);
}
}
Edit: agree with #MadProgrammer. It appears this is just an illustrative question, but you should make sure whatever you're trying to accomplish here you use a SwingWorker for.
I am running a very heavy process under an anonymous SwingWorker thread. In the meantime, I'm reporting progress to the GUI using a progress bar. However, Swing threading is doing me in. It's simply not updating anything in time. I'm not sure how to do it, as I've tried updating the GUI from the SwingWorker thread, and outside, and both refuse to work.
How can I reliably update the Swing UI while a heavy worker thread is running?
Things I've tried
This does not work (with or without wrapping in the invokeLater command).
new LocalCompressor(compressor).execute();
while (!compressionDone) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
int percent = compressor.getPercentDone();
progressBar.setValue(percent);
statusLabel.setText(percent);
}
});
}
Additionally, attempting to update the UI from a concurrent measuring thread does not work:
class LocalCompressor extends SwingWorker<Void, Void> {
// [...]
public LocalCompressor(Compressor compressor) {
this.compressor = compressor;
// [...]
}
#Override
protected Void doInBackground() {
final Thread t1 = new Thread(new Runnable() {
#Override
public void run(){
compressor.compress();
}
});
final Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
t1.start();
while (t1.isAlive()) {
updateUI(compressor.getPercentDone());
}
}
});
t2.start();
return null;
}
// [...]
}
You're not really using your SwingWorker. The worker already is a Thread for itself. If you have the possibility to put your long running code into the doInBackground(), put it there. Then just call publish(Integer) with your actual progress and process the chunks you get in the process(List<Integer>)-method. In process() you can update the gui, it's on the EDT.
EDIT:
Actually, what you're doing right now is polling in several-while loops, this is kinda power-consuming. That's why I think its better to you events in your algorithm, everytime you got a percent or everytime the loop starts a new round or something like that.
Did you try the very simple and basic way of using a SwingWorker? Like #Zhedar previously said, a SwingWorker already is a Thread for itself. So remove both your inner threads (t1, t2) and just use your time-consuming compress() method in doInBackground().
Something very basic like the following:
class LocalCompressor extends SwingWorker<Void, Integer> {
// .....
// Your constructor here
// .....
#Override
protected Void doInBackground() throws Exception {
compress();
return null;
}
#Override
protected void process(List<Integer> chunks) {
for (Integer chunk : chunks) {
progressBar.setValue(chunk);
statusLabel.setText(chunk);
}
}
}
Now this compress() method should be moved inside the SwingWorker and it must have somewhere a publish(), in your case it might be publish(getPercentDone()) or whatever.
private void compress() {
// .....
publish(getPercentDone());
// .....
}
This is how things are usually done with a SwingWorker.
Expanding on the answers and advice provided here already, here is one way to code it. I'm assuming the compressor itself has no ability to do callbacks but you can ask it for the percent done.
Within the swingworker thread (doInBackground) we start the real compression thread. Then start a polling loop in the background thread, to update the UI a few times a second. To notify the UI thread, call publish. This will cause the overridden method process to be called periodially in the event thread. From here we can safely update the progress bar and status label.
public class LocalCompressor extends SwingWorker<Void, Integer>
{
private Compressor compressor;
public LocalCompressor(Compressor compressor)
{
this.compressor = compressor;
// [...]
}
#Override
protected void done()
{
System.out.println("Compression is done. Going to do something with it...");
}
#Override
protected void process(List<Integer> chunks)
{
for (Integer percent : chunks)
{
progressBar.setValue(percent);
statusLabel.setText(percent);
}
}
#Override
protected Void doInBackground() throws Exception
{
final Thread t1 = new Thread(new Runnable()
{
#Override
public void run()
{
compressor.compress();
}
});
t1.start();
while (t1.isAlive())
{
int percentDone = compressor.getPercentDone();
publish(percentDone);
Thread.sleep(200);
}
return null;
}
}
You could employee a producer/consumer pattern...
Here's a really basic concept...
public class ProducerComsumer {
public static void main(String[] args) {
new ProducerComsumer();
}
public ProducerComsumer() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(new EmptyBorder(12, 12, 12, 12));
JProgressBar progressBar = new JProgressBar();
panel.add(progressBar);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Producer producer = new Producer();
producer.start();
Consumer consumer = new Consumer(producer, progressBar);
consumer.start();
}
});
}
public class Producer extends Thread {
private volatile float progress;
private volatile boolean done;
public Producer() {
setPriority(NORM_PRIORITY - 1);
setDaemon(true);
}
public float getProgress() {
return progress;
}
public boolean isDone() {
return done;
}
#Override
public void run() {
done = false;
for (int index = 0; index < Integer.MAX_VALUE; index++) {
progress = (float) index / (float) Integer.MAX_VALUE;
}
done = true;
System.out.println("All done...");
}
}
public class Consumer extends Thread {
private Producer producer;
private JProgressBar progressBar;
public Consumer(Producer producer, JProgressBar progressBar) {
setDaemon(true);
setPriority(NORM_PRIORITY - 1);
this.producer = producer;
this.progressBar = progressBar;
}
public JProgressBar getProgressBar() {
return progressBar;
}
public Producer getProducer() {
return producer;
}
#Override
public void run() {
while (!producer.isDone()) {
updateProgress();
try {
sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(ProducerComsumer.class.getName()).log(Level.SEVERE, null, ex);
}
}
updateProgress();
}
protected void updateProgress() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
int progress = Math.round(getProducer().getProgress() * 100f);
System.out.println("Update progress to " + progress);
getProgressBar().setValue(progress);
}
});
}
}
}
Have a play around with the Thread.setPriority values and see if it makes any difference
I'm assuming (ya know how that goes) that the call to LocalCompressor.execute() is blocking. If that's the case, your while loop won't run until it's all done, and then you're defeating the purpose of getting a steady stream of updates on your UI.
Give this, or something similar, a shot:
LocalCompressor comp = new LocalCompressor(compressor);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
while (!compressionDone) {
int percent = compressor.getPercentDone();
progressBar.setValue(percent);
statusLabel.setText(percent);
}
}
});
comp.execute();
}
I want to update a JLabel each time with the name of the file which I am downloading using FTPClient. I tried repaint(), validate(), revalidate(), first invalidate() and immediately validate()/revalidate() but still nothing is working.
My Code goes as follows:
if(ae.getActionCommand()=="Download"){
int[] row_indexes=table.getSelectedRows();
notifylb.setText("Downloading files");
this.validate();
for(int i=0;i<row_indexes.length;i++)
{
String fn=table.getValueAt(row_indexes[i], 0).toString();
notifylb.setText("Downloading: "+fn); // fn contains filename
this.validate();
this.downloadFtpfile(fn);
}
notifylb.setText("SUCCESSFULLY DOWNLOADED FILE(s) !");
this.validate();
}
Suggestions:
Don't use == to compare Strings. Instead use the equals(...) or equalsIgnoreCase(...) methods. The == operator returns true if the two String objects are the same, but this isn't what matters to you, but rather you want to check if both Strings hold the same characters in the same order, and this is what the two methods above check.
You're currently downloading your files on the Swing event dispatch thread or EDT, and this will not only prevent your JLabel from updating but will also cause your GUI to freeze since this thread is responsible for drawing all Swing graphics including its own components, and for Swing interaction with the user.
Calling repaint(), revalidate(), invalidate(), etc... will do nothing to solve this.
To solve this, do the downloading or any long-running process in a background thread. One way to do this is by creating a new Thread, loading it with a Runnable, and calling start, but there's a better way that is tailor made for Swing GUI's and that's to create a SwingWorker object and do your background coding in its doInBackground() method. The SwingWorker tutorials can help you figure out how to do this, and if you get stuck in your attempt, please come on back with your code.
You'll probably not want to mention your urgency as this often has the opposite effect intended. Please remember that we are all volunteers, that your urgency is truly your urgency not ours, and that no one likes to feel rushed or pressured to do something for someone else, especially volunteers.
Best of luck and welcome to stackoverflow.
Edit
Since you've seen an example of using plain Threads, I figured I'd post an example of what doing this with a SwingWorker object could look like:
if (ae.getActionCommand().equalsIgnoreCase("Download")) {
final int[] row_indexes = table.getSelectedRows();
notifylb.setText("Downloading files");
final List<String> fileNames = new ArrayList<String>();
for (int i = 0; i < row_indexes.length; i++) {
fileNames.add(table.getValueAt(row_indexes[i], 0).toString());
}
SwingWorker<String, String> downloadSwingWorker = new SwingWorker<String, String>(){
#Override
protected String doInBackground() throws Exception {
for (String fileName : fileNames) {
publish("Downloading: " + fileName);
downloadFtpfile(fileName);
}
return "SUCCESSFULLY DOWNLOADED FILE(s) !";
}
#Override
protected void process(List<String> chunks) {
for (String text : chunks) {
notifylb.setText(text);
}
}
#Override
protected void done() {
try {
String text = get();
notifylb.setText(text);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
};
downloadSwingWorker.execute();
}
Edit 2: corrected as per kleopatra's suggestion
#Hovercraft-Full-Of-Eels explain very clear, but if you need the code, here it is how to write it.
final JButton finalButton = button; // this is your button will trigger download
final JLabel finalLabel = finalLabel;
final JTable finalTable = table;
if(ae.getActionCommand().equals("Download"))
{
finalButton.setEnabled(false); //disable button, so user can not start it for twice until ftp finished.
Thread thread = new Thread(new Runnable()
{
#Override
public void run()
{
int[] row_indexes = finalTable.getSelectedRows();
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
finalLabel.setText("Downloading files");
}
});
for(int i = 0; i < row_indexes.length; i++)
{
final String fn = finalTable.getValueAt(row_indexes[i], 0).toString();
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
finalLabel.setText("Downloading: " + fn); // fn contains filename
}
});
this.downloadFtpfile(fn);
}
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
finalLabel.setText("SUCCESSFULLY DOWNLOADED FILE(s) !");
finalButton.setEnabled(true); //enable the button
}
});
}
});
thread.start();
};
First code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class cos {
public static int a;
private static JLabel labeler;
// public static Runnable r1;
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
a = 0;
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
cos window = new cos();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public cos() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
public void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 205, 194);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lblTime = new JLabel("Time:");
frame.getContentPane().add(lblTime, BorderLayout.WEST);
final JLabel labeler = new JLabel("");
frame.getContentPane().add(labeler, BorderLayout.CENTER);
JButton btnNewButton = new JButton("New button");
btnNewButton.addActionListener(new ActionListener() {
Runnable r1 = new Runnable() {
public void run() {
while (a <= 10) {
a = a + 1;
labeler.setText(Integer.toString(a));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
public void actionPerformed(ActionEvent arg0) {
Thread threder = new Thread(r1);
threder.start();
// liczniczek bla = new liczniczek();
}
});
frame.getContentPane().add(btnNewButton, BorderLayout.SOUTH);
}
public void licznik() {
while (a < 60) {
a = a + 1;
labeler.setText(Integer.toString(a));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
And now my question. I wanna use code like this:
Runnable r1 = new Runnable(){
public void run(){
licznik();
}
};
But that doesen't work. What i must do to separate this code ? Sorry for my bad english
Sierran.
never use Thread#sleep(int) during EDT, sure if is there only this thread then works correctly (with blockng EDT),
Runnable r1 = new Runnable(){
public void run(){
licznik();
}
};
is wrong than same as you call plain licznik();, you have to wrap that this way
Runnable r1 = new Runnable(){
public void run(){
labeler.setText(Integer.toString(a));
}
};
but again without Thread#sleep(int), you have three choises
1) change Thread to the javax.swing.Timer
2) change Thread to the Runnable#Thread, there you can delaying with Thread#sleep(int), but output to the GUI must be
Runnable r1 = new Runnable(){
public void run(){
labeler.setText(Integer.toString(a));
}
};
3) use SwingWorker, where output is in the EDT and you can use Thread#sleep(int) too
example Thread#sleep(int) during EDT
put all together
EDIT
don't use reserved words as class, method, variable, whatever Name in the Programing languages (meaning cos)
your code works by implements all three options that I post here,
What do you mean "it doesn't work"? It works for me. How are you trying to use this code, and what errors or problems are you having when you run it? Myself, I'd use a SwingWorker though and I'd set the JLabel's text via the SwingWorker's publish/process method pair. To learn more on how to use this, please see this tutorial: Concurrency in Swing
Edit
Actually, an easier way to accomplish what you want is to not use threads or Runnables directly at all but to use a Swing Timer as they're built for just this case. For more on this, please check out the Swing Timer Tutorial
I gather that you want the function licznik() to run in a separate thread. You create a Runnable, but you have to do something more to make its run() method execute. There are a couple of ways to do this:
Runnable r1 = new Runnable(){
public void run(){
licznik();
}
};
new Thread(r1).start();
or you can just subclass Thread directly:
Thread r1 = new Thread(){
public void run(){
licznik();
}
};
r1.start();
Runnable interface has no method licznik(). You can create class that implements Runnable with licznik() method.
Or if you do not need to reuse this method and use it just once, then the fastest way is to move its implementation inside new Runnable() block
Runnable r1 = new Runnable(){
public void run(){
this.licznik();
}
public void licznik(){
while (a < 60){
a = a + 1 ;
labeler.setText(Integer.toString(a));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
Look on GitHub under at https://github.com/greggwon/Ham. Look at the source code in https://github.com/greggwon/Ham/blob/master/SwingUtil/src/org/wonderly/swing/ComponentUpdateThread.java to see how I've packaged this whole detail into a single class which uses anonymous inner classes to do the work. It would be possible to change this to lambdas now, but I have not used Java in several years and thus haven't made that change.
new ComponentUpdateThread( new Action[] { add, del, edit } ) {
public void setup() {
super.setup();
list.setEnabled(false);
list.clearSelection();
}
public Object construct() {
try {
Vector v = remote.getData();
Collections.sort( v );
return v;
} catch( Exception ex ) {
reportException(ex);
}
return null;
}
public void finished() {
try {
Vector v = (Vector)getValue();
if( v != null ) list.setListData(v);
} finally {
super.finished();
list.setEnabled(true);
edit.setEnabled(false);
del.setEnaled(false);
}
}
}.start();
With this style of work, you can use final values from surrounding blocks or other class visible data to control various aspects of what happens before, during and after background thread execution.
I've change this code around over the years in various ways and there are other variations of this that exist.
The arguments to the ComponentUpdateThread constructor are controls/actions to be "disabled" while the background thread is running. Other enable/disable activities can be more literally embedded into the activities in setup() and finished() (which are run in the AWT event thread) before "construct" is run in the background thread.