Nodes in JTree not aligned when displayed

After adding a progress monitor, I noticed that my tree nodes don't align properly (see attached image).  If I click on one that is out of place, it will end up being aligned and displays the text.

Is there any obvious explanation for this?  It was not a problem before adding a progress monitor.  I don't see how the progress monitor would change this.  The code that expands is:

  private void expandTree()
  {
    for (int row = 0; row < tree.getRowCount(); row++) {
       tree.expandRow(row);
    }
  }
 misaligned tree
mock5cAsked:
Who is Participating?
 
objectsCommented:
>                   // Another way of setting progress...not used

you should be using that method
swing is single threaded, so you cannot update it from a different thread

> Also, if I do not expand the nodes automatically and leave the tree collapsed, when I manually expand, the nodes are not misaligned.  They are displayed correctly.

again, make sure you are expanding the nodes from the event dispatch thread
0
 
CEHJCommented:
You probably are blocking the event dispatch thread by not implementing the progress correctly. Best to use a SwingWorker. Please post code
0
 
mock5cAuthor Commented:
I've attached some of the code, which I think is sufficient to see how things are done.

Also, if I do not expand the nodes automatically and leave the tree collapsed, when I manually expand, the nodes are not misaligned.  They are displayed correctly.
// The button that is clicked
validateButton.addActionListener
(
  new ActionListener()
  {
    public void actionPerformed(ActionEvent ae)
    {
      validateButton.setEnabled(false);
      setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

      progressMonitor = new ProgressMonitor(MainFrame.this, "validating", "", 0, 100);
      progressMonitor.setProgress(0);

      task = new Task();
      task.execute();
    }
  }
);


// validate() is called by Task doInBackground()
private void validate() {

    ...

    final validator v = new Validator();
    final Random random = new Random();

    v.addPropertyChangeListener(
       new PropertyChangeListener()
       {

         public void propertyChange(PropertyChangeEvent e)
         {
            if (e.getPropertyName().equals("progress"))
            {
               try
               {
                  Thread.sleep(random.nextInt(100));
                  int newValue = (Integer) e.getNewValue();
                  progressMonitor.setProgress(v.getProgress());

                  // Another way of setting progress...not used
                  //EventQueue.invokeLater(new Runnable()
                  //{
                     //public void run()
                     //{
                        //progressMonitor.setProgress(v.getProgress());
                     //}
                  //});
               }
               catch (InterruptedException ignore) {}
            }
         }
      }
   );
   ...
}

public class Task extends SwingWorker<Void, Void>
{
  @Override
  public Void doInBackground()
  {
    final Random random = new Random();

    int progress = 0;
    setProgress(0);

    try {
      Thread.sleep(random.nextInt(1000));
      validate();
    }
    catch (InterruptedException ignore) {
      System.out.println("Interrupted Exception caught");
    }

    return null;
  }

  // After doInBackground() returns, this method is called from the EDT.
  @Override
  public void done()
  {
    setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
    validateButton.setEnabled(true);
    Toolkit.getDefaultToolkit().beep();
  }
}


///// In validator class

// validate() above calls a function with this code that processes each file.
int i = 0;
for(File file : files )
{
  // make sure we are looking at a file and not a directory.
  if (file.isFile())
  {
    System.out.println("this is where files are added");
    setProgress(100 * (i + 1)/files.size());
  }
  i++;
}

public int getProgress()
{
  return this.progress;
}

public void setProgress(int progress)
{
  int old = this.progress;
  this.progress = progress;
  this.pcs.firePropertyChange("progress", old, progress);
}

public void addPropertyChangeListener(PropertyChangeListener listener)
{
  this.pcs.addPropertyChangeListener(listener);
}

public void removePropertyChangeListener(PropertyChangeListener listener)
{
  this.pcs.removePropertyChangeListener(listener);
}

Open in new window

0
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

 
mock5cAuthor Commented:
I've confirmed that I am in fact not on the EDT.  The validate() function is invoked by the validateButton.  Here is where validation happens and then the tree is created.  The validate button becomes enabled in done() after doInBackground() completes.  So it is expected that the tree is drawn after validation.  Is there a way to switch back to EDT?

0
 
CEHJCommented:
>>The validate button becomes enabled in done() after doInBackground() completes

That will be called on the EDT
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.