Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

accessing variables and swing components through different threads

This question is related somewhat to the one i asked HERE. Now, i have a class "Controller" which consists of the main method and all the swing components. there is a class named "VTOL" which consists of a variable named "altitude"(i have declared this variable volatile as of now).

here is a class that consists of a thread which runs in the background:

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Vineet
 */
public class Gravity extends Thread {
    
    String altStr;
    double alt;
    Controller ctrl = new Controller();

    @Override
    public void run() {
        while (true) {
            alt=VTOL.altitude;
            System.out.println(alt);
            alt = alt-0.01;
            VTOL.altitude= (int) alt;
            altStr=new Integer(VTOL.altitude).toString();
            ctrl.lblAltitude.setText(altStr);
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }
}

Firstly, the problem i was facing initially was that i couldnt update value of "altitude" it remained 0 throughout the execution of program. So i declared it as volatile (I dont know if its a good practice)

Secondly, there is a jLabel in Controller class named "lblAltitude", i wish to update its value as its changed in this thread, but somehow thats not happening. How can i do that?

like image 766
md1hunox Avatar asked Jun 23 '12 17:06

md1hunox


People also ask

Is Java Swing multi threaded?

This means that most Swing components are, technically, not threadsafe for multithreaded applications. Now don't panic: it's not as bad as it sounds because there is a plan. All event processing in AWT/Swing is handled by a single system thread using a single system event queue. The queue serves two purposes.

Why Swing is not thread safe in Java?

Why Swing Components are not thread-safe. One of the main reason for Java Swing is not thread-safe is to simplify the task of extending its components. Another reason for the Java Swing is not thread-safe due to the overhead involved in obtaining and releasing locks and restoring the state.

Why is it recommended that you do not use components from AWT and Swing together in the same application?

Swing is built on top of AWT, with a different philosophy for creating and drawing UI components. Mixing UI components from the two frameworks could lead to unexpected results and was/is thus discouraged (as kleopatra states, this has been fixed).


1 Answers

A solution is to use a SwingPropertyChangeSupport object, to make altitude a "bound" property with this support object, to have your GUI listener to this model class and to thereby notify the GUI of changes in altitude.

e.g.,

import java.beans.PropertyChangeListener;
import javax.swing.event.SwingPropertyChangeSupport;

public class Gravity implements Runnable {
   public static final String ALTITUDE = "altitude";
   private SwingPropertyChangeSupport swingPcSupport = new SwingPropertyChangeSupport(this);
   private volatile double altitude;

   @Override
   public void run() {
      while (true) {
         double temp = altitude + 10;
         setAltitude(temp); // fires the listeners
         try {
            Thread.sleep(10);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }

   }

   public double getAltitude() {
      return altitude;
   }

   public void setAltitude(double altitude) {
      Double oldValue = this.altitude;
      Double newValue = altitude;

      this.altitude = newValue;

      // this will be fired on the EDT since it is a SwingPropertyChangeSupport object
      swingPcSupport.firePropertyChange(ALTITUDE, oldValue, newValue);
   }

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      swingPcSupport.addPropertyChangeListener(listener);
   }

   public void removePropertyChangeListener(PropertyChangeListener listener) {
      swingPcSupport.removePropertyChangeListener(listener);
   }


}

For a more complete runnable example:

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;

public class GravityTestGui extends JPanel {
   private static final long ALT_SLEEP_TIME = 400;
   private static final double ALT_DELTA = 5;
   JLabel altitudeLabel = new JLabel("     ");
   private Gravity gravity = new Gravity(ALT_SLEEP_TIME, ALT_DELTA);

   public GravityTestGui() {
      add(new JLabel("Altitude:"));
      add(altitudeLabel);

      gravity.addPropertyChangeListener(new PropertyChangeListener() {

         @Override
         public void propertyChange(PropertyChangeEvent pcEvt) {
            if (Gravity.ALTITUDE.equals(pcEvt.getPropertyName())) {
               String altText = String.valueOf(gravity.getAltitude());
               altitudeLabel.setText(altText);
            }
         }
      });

      new Thread(gravity).start();
   }

   private static void createAndShowGui() {
      GravityTestGui mainPanel = new GravityTestGui();

      JFrame frame = new JFrame("GravityTest");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }


}

class Gravity implements Runnable {
   public static final String ALTITUDE = "altitude";
   private SwingPropertyChangeSupport swingPcSupport = new SwingPropertyChangeSupport(this);
   private volatile double altitude;
   private long sleepTime;
   private double delta;

   public Gravity(long sleepTime, double delta) {
      this.sleepTime = sleepTime;
      this.delta = delta;
   }

   @Override
   public void run() {
      while (true) {
         double temp = altitude + delta;
         setAltitude(temp); // fires the listeners
         try {
            Thread.sleep(sleepTime);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }

   }

   public double getAltitude() {
      return altitude;
   }

   public void setAltitude(double altitude) {
      Double oldValue = this.altitude;
      Double newValue = altitude;

      this.altitude = newValue;

      // this will be fired on the EDT since it is a SwingPropertyChangeSupport object
      swingPcSupport.firePropertyChange(ALTITUDE, oldValue, newValue);
   }

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      swingPcSupport.addPropertyChangeListener(listener);
   }

   public void removePropertyChangeListener(PropertyChangeListener listener) {
      swingPcSupport.removePropertyChangeListener(listener);
   }
}
like image 131
Hovercraft Full Of Eels Avatar answered Oct 20 '22 09:10

Hovercraft Full Of Eels