title: JProgressBar not updating from SwingWorker, while debugs work fine
body: <p>This has been driving me up the wall for 2 days now. I can't seem to make the JProgressBar update properly and I'm not sure why. I've read through the concurrency and SwingWorker tutorials, I've tested outside of my program and been able to get it working fine using simple code. I understand the concepts, and am just not seeing why it's not working as the code has been re-written in many different ways and still I can't make it work. I'll post a SSCE using as much code from my program as I can, and explain things best I can here as well. </p>
  
  <p>Basically I have a auto-updater/Installer program to update and/or install World of Warcraft addons to our customers computers. The first thing the 'updater' does is check the server to see if it's version is the same as the version of the updater installer on the server. This works swimmingly! In fact the entire updater works great except for this one issue. If the updater sees that the server has a different version number than the updater it downloads the installer (in a zip) from the server, unzips it, starts the installation from the exe that was contained in the zip and closes the currently open updater so the install can complete properly. </p>
  
  <p>So I have a progress bar on the card (using cardLayout to show the three different cards for the updater, SelfUpdate, Login, and AddonList) for the self updater. as well as a JTextArea below the JProgressBar and that's all that shows on the particular SelfUpdate card. It query's the server for the version number on the server and it compares that version to the version  number on the updater currently installed. If the version is the same it changes to the Login card and moves along to the next bits of the program, which work great so far, if the versions are different it sends a query to the server and the server sends the zip file back to the updater for processing. </p>
  
  <p>This is where it's not working. The zip is a decent size and of course I want to show the progress of this download. The zip file download works fine (it runs in the SwingWorker doInBackground() method), the updater then unzips the installer.exe file to a folder on the customers system drive, fires off using Runtime and starts the installer.exe which pops up the installer screen, then closes the current updater using System.exit(0). again, all this works but the JProgressBar itself will NOT update. it sits at 0% for the whole thing. Also, the taskOutput JTextArea doesn't get updated either, but the main problem is the progressbar not updating. I can live with that getting fixed and the JTextArea not updating. (tried a JLabel in place of a textarea as well and no joy)</p>
  
  <p>So I know I'm doing something wrong, but I can't imagine what. Here's the bits where the magic happens. :) Forgive me if I explain as I go along here. </p>
  
  <p>So Controller.java handles all the flow of the program here's the parts you need to see. </p>
  
  <pre><code>// Imports packages needed for use in this file.
  import javax.swing.*;
  import java.awt.CardLayout;
  import java.io.*;
  // class instantiation
  public class Controller {
  
  // Variables needed for use in this class
  private static Updater util;
  private static int loginReturnState = 0;
  /**
  *   Single contructor for this class
  */
  public Controller() {
  
  }
  
  
  /**
  *   Main method which runes everything in the updater program
  *
  */
  public static void main(String[] args) {
      util = new Updater();
      // Schedule a job for the event dispatch thread.
      javax.swing.SwingUtilities.invokeLater(new Runnable() {
          public void run() {
  
              // setup a new GUI
              util.createGUI();
              JFrame rFrame = util.getRootFrame();                
              JPanel gFrame = util.getCardLayoutFrame();
              CardLayout cards = (CardLayout) gFrame.getLayout();
              cards.show(gFrame, "UpdateUpdaterPanel");
  
              rFrame.pack();
              rFrame.setLocationRelativeTo(null);
              rFrame.setVisible(true);
  
              SelfUpdater selfUp = new SelfUpdater();             
              int needUpdate = selfUp.checkForUpdate();                                       if (needUpdate == 2) {// Update available for download. Download it.
                  selfUp.downloadUpdate();
  
              } 
  
  
          }
      });
  
  
  }
  }
  </code></pre>
  
  <p>OK Next file is the Updater class. To put code in here that will hopefully compile and show the issue I need to put this class in there or the utility methods I have in the uPdater class will not be around to be called and I use them extensively. </p>
  
  <pre><code>// Packages needed for use in this file
  import javax.swing.*;
  import javax.swing.JFrame;
  import javax.swing.JPanel;
  import java.awt.*;
  import java.awt.CardLayout;
  import java.awt.event.MouseEvent;
  import java.awt.event.MouseListener;
  import java.awt.event.MouseMotionListener;
  import java.awt.event.MouseAdapter;
  import java.io.*;
  
  
  // Class instantiation
  public class Updater {
  
  // These final variables are set to the path for each of the images used
  public static final String BG_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\background.png";
  public static final String APP_ICON_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\app-icon.png";
  public static final String CLOSE_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\close.png";
  public static final String FINOFF_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\FinishedOff.png";
  public static final String FINON_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\FinishedOn.png";
  public static final String ICON_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\icon.png";
  public static final String ICON64_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\icon64x64.png";
  public static final String ICON256_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\icon256x256.png";
  public static final String INSTOFF_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\InstallUpdatesOFF.png";
  public static final String INSTON_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\InstallUpdatesON.png";
  public static final String LOGO_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\logo.png";
  public static final String MIN_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\minimize.png";
  public static final String PROGBACK_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\ProgressBackground.png";
  public static final String PROGBAR_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\ProgressBar.png";
  public static final String INSTRUCTIONS_BUTTON = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\instructions.png";
  public static final String PURCHASE_BUTTON = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\Purchase.png";
  // These are various final variables for use throughout the updater
  public static final String URL_CONNECT = "http://dynastyaddons.com/api/index2.php?";
  public static final String TITLE_TEXT = "Dynasty Updater";
  public static final int BUFFER_SIZE = 4096;
  public static final double UPDATER_VERSION = 1.1;
  
  // Public variables needed for this class workings
  private static JFileChooser fc;
  private static JFrame rootFrame;
  
  // Private variables for this class use alone
  private static String PHPSessionID;
  private static boolean debugToggle = true;
  private CardLayout cards;
  private JPanel guiFrame;
  private Point mouseDownCompCoords;
  private Login login;
  private Addons addons;
  
  /**
  *   Sole contructor. (For invocation by subclass contructors, typically implicit.)
  */
  public Updater() {
      // First instantiate any variables needed
      PHPSessionID = "notset";
      guiFrame = new JPanel();
      cards = new CardLayout();
      guiFrame.setLayout(cards);
  }
  
  
  // Various methods follow
  /**
  *   This will create the root gui for showing in the main method
  *
  */
  public void createGUI() {
      rootFrame = new JFrame();
      SpringLayout rootLayout = new SpringLayout();
  
      // setup root frame
      rootFrame.setUndecorated(true);
      rootFrame.setBackground(new Color(0,0,0,0));
      rootFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      rootFrame.setPreferredSize(new Dimension(800,600));
      rootFrame.setTitle(TITLE_TEXT);
  
      // add the background image
      JLabel bg = new JLabel(new ImageIcon(BG_IMAGE_PATH));
      bg.setLayout(rootLayout);
      rootFrame.add(bg);
  
      // setup title bar
      mouseDownCompCoords = null;
      mouseDownCompCoords = null;
      rootFrame.addMouseListener(new MouseListener() {
          public void mouseReleased(MouseEvent e){ mouseDownCompCoords = null; }
          public void mousePressed(MouseEvent e){ mouseDownCompCoords = e.getPoint(); }
          public void mouseExited(MouseEvent e){}
          public void mouseEntered(MouseEvent e){ }
          public void mouseClicked(MouseEvent e){ }
      });
      rootFrame.addMouseMotionListener(new MouseMotionListener() {
          public void mouseMoved(MouseEvent e){}
          public void mouseDragged(MouseEvent e){
              Point currCoords = e.getLocationOnScreen();
              rootFrame.setLocation(currCoords.x - mouseDownCompCoords.x, currCoords.y - mouseDownCompCoords.y);
          }
      });
  
      // Display and place the logo
      JLabel logo = new JLabel(new ImageIcon(LOGO_IMAGE_PATH));
      bg.add(logo);
  
      // add Close and Minimize buttons
      JPanel cmButt = createCloseAndMinButtons();
      bg.add(cmButt);
  
      // create card frame
      guiFrame.setPreferredSize(new Dimension(800, 435));
      guiFrame.setOpaque(false);
      bg.add(guiFrame);
  
      // Constrain the parts of your BG
      rootLayout.putConstraint(SpringLayout.WEST, logo, 30, SpringLayout.WEST, rootFrame);
      rootLayout.putConstraint(SpringLayout.NORTH, logo, 70, SpringLayout.NORTH, rootFrame);
      rootLayout.putConstraint(SpringLayout.NORTH, cmButt, 0, SpringLayout.NORTH, rootFrame);
      rootLayout.putConstraint(SpringLayout.EAST, cmButt, 0, SpringLayout.EAST, rootFrame);
      rootLayout.putConstraint(SpringLayout.SOUTH, guiFrame, 0, SpringLayout.SOUTH, rootFrame);
      rootLayout.putConstraint(SpringLayout.WEST, guiFrame, 0, SpringLayout.WEST, rootFrame);
      rootLayout.putConstraint(SpringLayout.EAST, guiFrame, 0, SpringLayout.EAST, rootFrame);
  
  
      // Create self updater panel and get it ready to show
      SelfUpdater selfUp = new SelfUpdater();
      JPanel selfUpd = selfUp.getSelfUpdatePanel();
  
              // get the cardlayout and add the three panels to it, then show the self-updater to begin.
  
      guiFrame.add(selfUpd, "UpdateUpdaterPanel");    }
  
  /**
  *   Creates a panel which has the close and minimize buttons on it.
  */
  private static JPanel createCloseAndMinButtons() {
      JPanel a = new JPanel();
      SpringLayout closeLO = new SpringLayout();
      a.setLayout(closeLO);
      a.setPreferredSize(new Dimension(150,150));
      a.setOpaque(false);
  
      // Close Button
      JButton cButt = new JButton(new ImageIcon(Updater.CLOSE_IMAGE_PATH));
      cButt.setBorderPainted(false);
      cButt.setContentAreaFilled(false);
      cButt.setFocusPainted(false);
      cButt.setOpaque(false);
      cButt.addMouseListener(new MouseAdapter() {
          @Override
          public void mouseClicked(MouseEvent e) { System.exit(0); }
      });
      a.add(cButt);
  
      // Minimize Button
      JButton mButt = new JButton(new ImageIcon(Updater.MIN_IMAGE_PATH));
      mButt.setBorderPainted(false);
      mButt.setContentAreaFilled(false);
      mButt.setFocusPainted(false);
      mButt.setOpaque(false);
      mButt.addMouseListener(new MouseAdapter() {
          @Override
          public void mouseClicked(MouseEvent e) { rootFrame.setState(JFrame.ICONIFIED); }
      });
      a.add(mButt);
  
      // Constrain parts on panel
      closeLO.putConstraint(SpringLayout.EAST, cButt, 12, SpringLayout.EAST, a);
      closeLO.putConstraint(SpringLayout.NORTH, cButt, -2, SpringLayout.NORTH, a);
      closeLO.putConstraint(SpringLayout.EAST, mButt, 30, SpringLayout.WEST, cButt);
      closeLO.putConstraint(SpringLayout.NORTH, mButt, -2, SpringLayout.NORTH, a);
  
      // Return the jframe
      return a;
  
  }
  
  /**
  *   Returns the guiFrame which holds the cardlayout for the changing of the panels.
  *
  *   @return JPanel  Returns the frame which holds the cardlayout.
  */
  public JPanel getCardLayoutFrame() {
      return guiFrame; 
  }   
  
  /**
  *   This will return the cardlayout for use in the controller.
  *
  *   @return CardLayout  Returns the cardlayout for use in the Controller.
  */
  public CardLayout getCardLayout() { return cards; }
  
  
  /**
  *   Returns the current version of this updater as a double
  *
  *   @return     the version of this updater as a double.
  */
  public double getUpdaterVersion() { return UPDATER_VERSION; }
  
  /**
  *   Returns a string that tells if the customer is useing windows or mac
  *
  *   @return     the operating system in use by the customer
  */
  public static String getOSType() {
      String retString = "";
      String oST = System.getProperty("os.name").toLowerCase();
      int spacePos = oST.indexOf(" ");
      if (spacePos &gt; 0) {
          retString = oST.substring(0, spacePos);
      }
      retString.trim();
      return retString;
  }
  
  
  /**
  *   Returns the main root frame for display purposes in controller.java
  *
  *   @return JFrame  returns rootFrame.
  */
  public JFrame getRootFrame() { return rootFrame; }
  
  }
  </code></pre>
  
  <p>OK&lt; Keep in mind this class really just does some utility stuff in the background and likely isn't involved in anything other than creatin the background gui and tellin the SelfUpdate card to show up.  </p>
  
  <p>Finally here's the SelfUpdater.java file which displays the SelfUpdater panel with the progress bar in it and does all the server querying which works fine again. Pay attention to the System.out.println debug statements I have in the downloadUpdate method (which is called in the controller file), as they work fine and print out in the console no problem. The selfUpdateProgress.setValue(int) and taskOutput.setText(txt) statements in that method do nothing .Also I've put a println in the doInBackground where it does setProgress(int) and that prints to the console fine but the bar doesn't update with setProgress. Here it is. </p>
  
  <pre><code>import java.awt.*;
  import java.awt.event.*;
  import java.beans.*;
  import javax.swing.*;
  import java.io.*;
  import java.net.*;
  import java.util.zip.*;
  
  // Create and start class
  public class SelfUpdater extends JPanel {
  
  // These are the variables needed for use in this class
  private JPanel selfUpdatePanel;
  private JProgressBar selfUpdateProgress;
  private Task task;
  private JTextArea taskOutput;
  private Updater util;
  
  /**
  *   Default class constructor, instantiates variables and sets up GUI.
  *
  *
  **/
  public SelfUpdater() {
      // Progress Bar
      selfUpdateProgress = new JProgressBar(0, 100);
      selfUpdateProgress.setValue(0);
      selfUpdateProgress.setStringPainted(true);
      selfUpdateProgress.setPreferredSize(new Dimension(470,29));
  
      // Layout
      SpringLayout selfUpdateLayout = new SpringLayout();
      SpringLayout pBarLayout = new SpringLayout();
  
  
      // Font and color setup for Task Output
      Font myFont = new Font("Serif", Font.BOLD, 16);
      Color myColor = new Color(255, 170, 0);
  
  
      // Description of progress pane
      taskOutput = new JTextArea("Checking server for updates to the updater.", 1, 39);
      taskOutput.setFont(myFont);
      taskOutput.setForeground(myColor);
      taskOutput.setEditable(false);
      taskOutput.setOpaque(false); // this is false after setting up the window.
  
      //extras needed for the class workings
      util = new Updater();
  
      // Images for progress bar setup
      JLabel pBar = new JLabel(new ImageIcon(util.PROGBACK_IMAGE_PATH));
      pBar.setOpaque(false);
      //pBar.setLayout(pBarLayout);
      //pBar.add(taskOutput);
      //pBar.add(selfUpdateProgress);
  
      // Main panel
      selfUpdatePanel = new JPanel();
      selfUpdatePanel.setPreferredSize(new Dimension(800, 435));
      selfUpdatePanel.setLayout(selfUpdateLayout);
      selfUpdatePanel.setOpaque(false); 
      selfUpdatePanel.add(taskOutput);
      selfUpdatePanel.add(selfUpdateProgress);
      selfUpdatePanel.add(pBar);  
  
      // Constrain your bits.
      // First constrain PBar to the self update panel
      selfUpdateLayout.putConstraint(SpringLayout.SOUTH, pBar, -40, SpringLayout.SOUTH, selfUpdatePanel);
      selfUpdateLayout.putConstraint(SpringLayout.WEST, pBar, 150, SpringLayout.WEST, selfUpdatePanel);
      selfUpdateLayout.putConstraint(SpringLayout.SOUTH, taskOutput, -50, SpringLayout.SOUTH, selfUpdatePanel);
      selfUpdateLayout.putConstraint(SpringLayout.WEST, taskOutput, 175, SpringLayout.WEST, selfUpdatePanel);
      selfUpdateLayout.putConstraint(SpringLayout.SOUTH, selfUpdateProgress, -84, SpringLayout.SOUTH, selfUpdatePanel);
      selfUpdateLayout.putConstraint(SpringLayout.WEST, selfUpdateProgress, 171, SpringLayout.WEST, selfUpdatePanel); }
  
  /**
  *   Will return the jpanel that contains the gui elements for the Self-Update
  *
  *   @return JPanel  The Self-Update gui.
  *
  */
  public JPanel getSelfUpdatePanel() { return selfUpdatePanel; }
  
  /**
  *   This will check the server to see if an update is available for the updater
  *
  *   @return int     Returns an int that will describe the answer from the server.
  *                   Possible Return values:
  *                   0 = Problem checking for update: Server return NULL
  *                   1 = Second type of problem checking for update: Server returned empty string
  *                   2 = Update available.
  *                   3 = Update not needed.
  *
  */
  public int checkForUpdate() {
      // ask the server what version it's updater is.
      String serverUpdaterVersion = "";
  
      try {
  
          HttpConnect conn = new HttpConnect();
          String urlRequest = util.URL_CONNECT + "action=get_updater&amp;platform=" + util.getOSType();
          serverUpdaterVersion = conn.textRequest(urlRequest, 1);
  
      } catch (MalformedURLException e) {
          JOptionPane.showMessageDialog(null, "We were unable to connect to the server while checking for an updater update, please check your internet connection.", "Attention!",JOptionPane.ERROR_MESSAGE);            
      } catch (IOException e) {
          JOptionPane.showMessageDialog(null, "We were unable to open the connection to the server while checking for an updater update, please check your internet connection.", "Attention!",JOptionPane.ERROR_MESSAGE);        
      }
  
      // check for errors and return proper int.
      if (serverUpdaterVersion == null) { // There is an error if the server returns null, return 0
          return 0;
      } else if (serverUpdaterVersion.equals("")) { // if the server returns an empty string return 1 for an error
          return 1;
      } else { // not null or empty string. check versions
          // Check version of this updater to servers version
          double sVers = Double.parseDouble(serverUpdaterVersion);
  
          if((double)sVers == util.getUpdaterVersion()) { // return 3 if no update needed here.
              return 3;
          } else { // otherwise return 2 so we can get the update
              return 2;
          }
  
      }
  }
  
  /**
  *   This will download the update from the server.
  *
  *   @return File        The downloaded file from the server. A zip file usually.
  *
  */
  public void downloadUpdate() {
      // turn on wait cursor
      util.getRootFrame().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
  
      // start a new task which does the download
      // Instances of javax.swing.SwingWorker are not reusuable, so
      // we create new instances as needed.
      task = new Task();
      // add a property listener to the task so it knows to update the progress meter.
      task.addPropertyChangeListener(new PropertyChangeListener() {
          @Override
          public void propertyChange(PropertyChangeEvent evt) {
  
              switch(evt.getPropertyName()) {
                  case "progress":// set the progress value and the task output value.
                      selfUpdateProgress.setIndeterminate(false);
                      int prg = (Integer) evt.getNewValue();
                      selfUpdateProgress.setValue(prg);
                      taskOutput.setText("Downloading and unzipping update. Progress = " + prg + "%");
                      System.out.println("Percent progress: " + prg + "%");
                      break;
              }
          }
      });
      // execute or start the task.
      task.execute();
  }
  
  /**
  *   This method will unzip the downloaded file, and start the installation.
  *   Then it will close this program while the installation completes.
  *
  *
  */
  public void unzipNewUpdater() {
      // create strings for naming the zip file to open up and where to put it.
      String zipFile = "NewUpdater.zip";
      String outputFolder = System.getenv("SystemDrive") + "\\DynastyAddons";
      // Try the unzipping and catch any errors.
      try {
  
          // Setup the input stream and get the entry ready to unzip.
          ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile));
          ZipEntry ze = zis.getNextEntry();
  
          // loop to open each entry and output it to the output folder and file.
          while(ze!=null) {
              // Get the name
              String entryName = ze.getName();
  
              // get the file to unzip
              File f = new File(outputFolder + File.separator + entryName);
  
              // Create folders needed to hold the unzipped stuff
              f.getParentFile().mkdirs();
  
              // get output stream setup to copy the file to from the zip
              FileOutputStream fos = new FileOutputStream(f);
  
              // get length of file to make sure we get the whole thing moved
              int len;
              byte buffer[] = new byte[1024];
  
              // loop thru the entry writing the whole file to the output directory
              while((len = zis.read(buffer)) &gt; 0){
                  fos.write(buffer, 0, len);
              }
  
              // close the output stream and get the next entry ready for the next iteration of the loop.
              fos.close();
              ze = zis.getNextEntry();
  
          }
  
          // close the entry and input stream since we're done.
          zis.closeEntry();
          zis.close();
  
      } catch (FileNotFoundException ex) {
          // throw error
      } catch (IOException ex) {
          // throw error
      }
  }
  
  // This private class handles the download and unzip of the new updater if needed.
  class Task extends SwingWorker&lt;Void, Void&gt; {
  
  
      @Override
      public Void doInBackground() {
          try {
              HttpConnect conn = new HttpConnect();
              String downloadURL = util.URL_CONNECT + "action=download_updater&amp;platform=" + util.getOSType();
              conn.downloadFile(downloadURL);
  
              InputStream inputStream = conn.getInputStream();
  
              FileOutputStream outputStream = new FileOutputStream(System.getenv("SystemDrive") + "\\DynastyAddons\\NewUpdater.zip");
  
              byte[] buffer = new byte[util.BUFFER_SIZE];
              int bytesRead = -1;
              long totalBytesRead = 0;
              int percentCompleted = 0;
              long fileSize = conn.getContentLength();
  
              taskOutput.setText("Downloading Newest Updater.");
              //setProgress(0);
  
              while ((bytesRead = inputStream.read(buffer)) != -1) {
  
                  outputStream.write(buffer, 0, bytesRead);
                  totalBytesRead += bytesRead;
                  percentCompleted = (int) (totalBytesRead * 100 / fileSize);
                  setProgress(percentCompleted);
  
              }
  
              outputStream.close();
              conn.disconnect();
  
          } catch (IOException ex) {
              JOptionPane.showMessageDialog(util.getRootFrame(), "Error downloading Updater file. Please send this entire error to support@dynastyaddons.com. \n Error: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
              setProgress(0);
          }
          return null;
      }
  
      @Override
      public void done() {
          // Create msg window saying update downloaded.
          JOptionPane.showMessageDialog(util.getRootFrame(), "The new updater has been downloaded. \nClick OK to close this updater and start the installation of the new version.", "Attention", JOptionPane.PLAIN_MESSAGE);
  
          // Unzip the updater
          unzipNewUpdater();
  
          // Tell the cursor we're not busy anymore
          setProgress(100);
          selfUpdateProgress.setValue(100);
          taskOutput.setText("Done Downloading New Updater. Installing...");
          util.getRootFrame().setCursor(null);
  
          // Create command used to open the udpater installer.
          String cmd = "cmd /c " + System.getenv("SystemDrive") + "\\DynastyAddons\\InstallDynastyAddonsUpdater.exe";
  
          // Here is where we run the exe that will install the new updater.
          try{
              Runtime.getRuntime().exec(cmd);
          }catch (FileNotFoundException ex){
              // handle this error
          }catch (IOException ex) {
              // handle this error
          }
  
          // Now close this updater so the new one can install.
          System.exit(0);
      }
  }
  
  }
  </code></pre>
  
  <p>I'm hopin it'll all compile properly if you need to see it working. If not let me know and i'll update stuff to make it work on a compile. So I've tried a number of things, making the SelfUpdater class implement PropertyChangeListener and implementing PropertyChange(event), I've tried feeding the JProgressBar to a constructor in the Task class. I've tried outputting an Integer in the SwingWorker and using Publish and Process to update the taskOutput and JProgressBar, I've tried re-writing the whole damn class to fix up the code and make it eaiser to pick out issues. I've done tests using the tutorials and some of my code to make it work (they worked great) but every time I come back to my updater code here, the darn progressbar wont update. I'm really prayin someone can give me a bit of insight on this problem so I can wrap up this project and start on something new! This is the very last thing I have to fix (unless there's problems on the Mac) and I'm done it and can go back to testing and getting it distributed to our customers. </p>
  
  <p>Feel more than free to comment on any part of the code as well (anything I maybe did stupid or something) I'm always lookin for critisim on my code especially if I'm not doing something according to good design and.. ugh brain froze forgot the word here. and definitely if more info is needed I can easily just paste in all the code in the 7 classes that make up this updater. </p>
  
  <p>It all compiles, and works fine, except this jprogressbar wont display the progress, even tho I can get it to pring out in the console. Thank you in advance, sorry for the mini-novel here, Haven't had to ask a question yet, and have been able to figure everything eout from other peoples questions and answers, just stumped now and ready to be done with this! :D </p>
  
  <p>I apologize in advance if I've screwed something up in the post here, remember it's my first post and while I've read hundreds of them, I'm sure my noobness has messed something up so feel free to castigate me for my mistakes so I can fix them. :)</p>
  
  <p><strong>EDIT</strong> Updated the selfUpdater.java to reflect using of only one spring layout.</p>