0

I have my thread

this.clock = new JLabel();
clockThread = new Thread(new Runnable() {
      public void run() {
            clockRun();
        }
    });
clockThread.start();
this.clock.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            if (clockDisplayRealTime) {
                clockDisplayRealTime = false;
            } else {
                clockDisplayRealTime = true;
            }
        }

    });

then this will not work unless I have this System.out.println as per below I am scratching my head to find out what is wrong. please help me. thanks.

public void clockRun() {
        while (true) {
            System.out.println(clockDisplayRealTime);
            if (clockDisplayRealTime) {
                Date date = new Date();
                clockRealtime = date.getTime();
                this.clock.setText(sdf.format(clockRealtime));
            }
        }
    }
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • Maybe it's updating too fast? – OneCricketeer May 23 '17 at 10:06
  • yeah! agreed with @cricket_007 - add logging statement to `mouseClicked()` and also what do you initialise `clockDisplayRealTime` with ? I would also add `Thread.sleep(200)` in `clockRun()` otherwise you are hammering CPU a lot just to display some text. – diginoise May 23 '17 at 10:07
  • Since, Swing is not NOT thread safe, it would be wiser to use a Swing `Timer` or `SwingWorker` instead of a plain old `Thread`, which then gives you more control over turning them on and off. [A `SwingWorker` example](https://stackoverflow.com/questions/44103925/why-is-my-looping-gui-timer-not-showing-up/44105478#44105478) and [a `Timer` example](https://stackoverflow.com/questions/27160592/java-gui-clock-using-large-amounts-of-ram/27160772#27160772) – MadProgrammer May 23 '17 at 10:37
  • 1
    You might want to read up on [Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/), [How to use Swing Timers](http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html) and [Worker Threads and SwingWorker](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html) – MadProgrammer May 23 '17 at 10:39
  • 1
    As suggested [here](https://stackoverflow.com/q/9459657/230513), `println()` may be surreptitiously synchronizing your errant code. – trashgod May 23 '17 at 10:46

2 Answers2

0

needs volatile

volatile private boolean clockDisplayRealTime = false;

this question was duplicated

0

Swing components should only be mutated on the Event Dispatch Thread.

The easiest way to solve your problem is probably a SwingWorker. You can also do it by hand as follows:

clockThread = new Thread(() -> {
    while (true) {
        if (clockDisplayRealTime) {
            SwingUtilities.invokeAndWait(() -> {
                Date date = new Date();
                clockRealtime = date.getTime();
                this.clock.setText(sdf.format(clockRealtime));
            });
            Thread.sleep(1000); // no need to update the UI more often than that
        }
    }
});    

The reason your code fails is that several threads accessed the same field without synchronization, in which case the Java memory model does not guarantee that changes done by one thread will become visible to another. By putting all code accessing the clockDisplayRealTime field into the same thread, you neatly sidestep this issue.

meriton
  • 68,356
  • 14
  • 108
  • 175
  • Oh, I don't know, I think a Swing `Timer` would be easier, you can `start` and `stop` a `Timer` more easily than a `SwingWorker` ;) – MadProgrammer May 23 '17 at 10:39
  • SwingUtilities.invokeAndWait(() -> { carefully EDT must be tested, there must be false as returns from isEventDIspatchThread..., otherwise RepaintManager returns an Exceptions – mKorbel May 23 '17 at 16:47