1

I am trying to make this work. I create a window, with one text field and button, then I run the run() method which should refresh text in textfield, and when I click on button it should iterate number by 1. I want to make this work simultaneously but I am stuck. It just iterates the number but do not refresh a value in textfield.Could you please help me somehow? I thought its easy to learn about Threads but...no :-D Here is the code.

Window class

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton; 
import javax.swing.JFrame;
import javax.swing.JTextField;

@SuppressWarnings("serial") 
public class Okno extends JFrame implements ActionListener,Runnable {

    private JFrame o = new JFrame();
private static JTextField t = new JTextField();
private JTextField t2 = new JTextField();
private static int x = 0;
protected JButton b = new JButton("KLIK");


Okno() {

    o.setVisible(true);
    o.setBounds(0, 0, 300, 200);
    o.setLayout(null);
    o.setDefaultCloseOperation(EXIT_ON_CLOSE);

    t.setBounds(10, 10, 60, 20);
    t2.setBounds(80, 10, 60, 20);
    b.setBounds(50, 80, 60, 30);
    b.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            while (true) {
                Okno.work();
                System.out.println("Klik");
            }

        }
    });
    o.add(t);
    o.add(b);
    o.add(t2);
}
public static int iter(){

    x++;
    return x;
}

public static void work(){
    try {
        iter();
        System.out.println(x);
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
@Override
public void actionPerformed(ActionEvent e) {

}
@Override
public void run() {
    while(true){
        try {
            Thread.sleep(1200);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    t.setText(Integer.toString(x));
    System.out.println("RUN");
    }
}
    }

Main Class

public class ThreadDemo {
public static void main(String args[]) {
 Okno o = new Okno();

 while(true){
 o.run();
 }
 }
 }
2
  • 1
    Your code ignores Swing threading rules by trying to make Swing calls on a background thread and by calling Thread.sleep(...) on the Swing event thread. Either use a Swing Timer (as per an answer) or use a SwingWorker to be sure that Swing method calls are only made on the Swing event thread. There are tutorials that cover this which you should be able to find. Commented Apr 21, 2013 at 14:37
  • 1
    Thanks for advice Mr D! I am stuck with this for hours this may solve the problem. Commented Apr 21, 2013 at 14:37

1 Answer 1

2

Swing is single threaded. Calling Thread.sleep prevents UI updates. Use a Swing Timer instead.

From GETah's answer to java stopwatch that updates gui every second:

Something along these lines should do it:

import java.awt.EventQueue;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.JLabel;

/** @see https://stackoverflow.com/a/11058263/230513 */
public class Clock {

    private Timer timer = new Timer();
    private JLabel timeLabel = new JLabel(" ", JLabel.CENTER);

    public Clock() {
        JFrame f = new JFrame("Seconds");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(timeLabel);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
        timer.schedule(new UpdateUITask(), 0, 1000);
    }

    private class UpdateUITask extends TimerTask {

        int nSeconds = 0;

        @Override
        public void run() {
            EventQueue.invokeLater(new Runnable() {

                @Override
                public void run() {
                    timeLabel.setText(String.valueOf(nSeconds++));
                }
            });
        }
    }

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                final Clock clock = new Clock();
            }
        });
    }
}

The timeLabel will always display the number of seconds the timer has been running.

  1. You will need to correctly format it to display "hh:mm:ss"; one approach is shown here.

  2. Create a container and add the label to it so that you can display it as part of the GUI.

  3. Compare the result to this alternate using javax.swing.Timer.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.