Java Qt Extensions

Examples

Example9 - Threads

This example demonstrates threads handling.

All methods of QSwing components are reentrant i.e. they can be called from other threads but they are not thread-safe. Unlike Swing all method calls from other threads are automatically scheduled and executed inside the GUI event loop. A calling thread is blocked until a call returns (implicit invokeAndWait).
All QSwing native objects live in the GUI thread (a thread that runs the GUI event loop) regardless of the thread in which their Java counterparts are created. Even though the objects can be accessed from other threads it is preferable that they are created and used inside the GUI thread. This is due to performance reasons.

Code

package yu.ac.bg.etf.javaqx.examples;

import java.util.Random;

import yu.ac.bg.etf.javaqx.qswing.JQButton;
import yu.ac.bg.etf.javaqx.qswing.JQContainer;
import yu.ac.bg.etf.javaqx.qswing.JQProgressBar;
import yu.ac.bg.etf.javaqx.qswing.QSwing;
import yu.ac.bg.etf.javaqx.qswing.events.ActionEvent;
import yu.ac.bg.etf.javaqx.qswing.events.ActionListener;

/**
 * Threads Example.
 */
public class Example9Threads extends JQContainer {

  final JQProgressBar progressBar1;
  final JQProgressBar progressBar2;
  final JQButton button;
  final RandomThread randomThread11;
  final RandomThread randomThread12;
  final RandomThread randomThread21;
  final RandomThread randomThread22;

  /**
   * GUI Building.
   */
  public Example9Threads() {
    super(null);
    setName("Threads");
    setFixedSize(300100);
    progressBar1 = new JQProgressBar();
    progressBar1.setValue(50);
    add(progressBar1);
    progressBar1.setBounds(101027420);
    progressBar2 = new JQProgressBar();
    progressBar2.setValue(50);
    add(progressBar2);
    progressBar2.setBounds(104027420);
    button = new JQButton("Pause");
    add(button);
    button.setBounds(120706025);
    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        if (randomThread11.isWorking()) {
          randomThread11.pauseTimer();
          randomThread12.pauseTimer();
          randomThread21.pauseTimer();
          randomThread22.pauseTimer();
          button.setText("Resume");
        else {
          randomThread11.resumeTimer();
          randomThread12.resumeTimer();
          randomThread21.resumeTimer();
          randomThread22.resumeTimer();
          button.setText("Pause");
        }
      }
    });
    randomThread11 = new RandomThread(progressBar1);
    randomThread12 = new RandomThread(progressBar1);
    randomThread21 = new RandomThread(progressBar2);
    randomThread22 = new RandomThread(progressBar2);
  }

  /**
   * Non-GUI Thread.
   */
  static class RandomThread extends Thread {
    private static final Random random = new Random();
    private boolean pause;
    private final JQProgressBar progressBar;
    public RandomThread(JQProgressBar progressBar) {
      this.progressBar = progressBar;
      setDaemon(true);
      start();
    }
    public synchronized boolean isWorking() {
      return !pause;
    }
    public synchronized void pauseTimer() {
      pause = true;
      notifyAll();
    }
    public synchronized void resumeTimer() {
      pause = false;
      notifyAll();
    }
    public void run() {
      try {
        while (true) {
          sleep(500 + random.nextInt(1000));
          synchronized (this) {
            while (pause) {
              wait();
            }
          }
          int value = 50 (int)(40 * random.nextGaussian());
          progressBar.setValue(value)// <-- a regular call from non-GUI thread
        }
      catch (InterruptedException e) {
      }
    }
  }

  public static void main(String[] args) {
    Example9Threads threadsExample = new Example9Threads();
    threadsExample.setVisible(true);
    QSwing.startEventLoop(true);
  }

}

Screenshots

Threads on
Windows Vista
Threads on
Windows XP
Threads on
Windows 98
Threads on
SUSE Linux
Threads on
Ubuntu Linux