How to layout a graph in a separate thread

Questions & Answers

Summary

Explains how to invoke a layout algorithm from within a desktop application so that the GUI stays responsive while the layout is being calculated.
For a better user experience, please go to the integrated documentation viewer to read this article.

Description

Starting with version 2.7 yFiles for Java Complete provides the new class Graph2DLayoutExecutor which eases performing a layout. It provides an easier way of running a layout in a separate thread than the one described below. We recommend using Graph2DLayoutExecutor, if your distribution includes it.

Since the calculation of a graph layout may take a long time, it is desirable to invoke a layout algorithm within a separate thread so that the GUI of the application stays responsive. Ensuring that the graph can be properly displayed while it is being laid out requires that the layout algorithm works on a copy of the graph. The layout result needs to be applied to the original graph in a synchronized manner.

The following code represents an action event code that invokes a layout algorithm within a separate thread.

class ThreadedLayoutAction extends AbstractAction {
  boolean layoutMorphingEnabled = true;

  public ThreadedLayoutAction() {
    super("Threaded Layout");
  }

  public void actionPerformed(ActionEvent ev) {
    final OrganicLayouter layouter = new OrganicLayouter();
    // Copy graph in AWT thread.
    final CopiedLayoutGraph cGraph = new CopiedLayoutGraph(view.getGraph2D());

    // Calculate a layout on the copy of the original graph within a separate 
    // thread.
    final Thread thread = new Thread() {
      public void run() {
        layouter.doLayout(cGraph);

        // Assign the calculated layout to the original graph within the AWT 
        // thread.
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            if (layoutMorphingEnabled) {
              // Perform an animated morphing on layout result.
              GraphLayout gl = cGraph.getLayoutForOriginalGraph();
              new LayoutMorpher(view, gl).execute();
            }
            else {
              // Assign the layout directly without morphing and display the 
              // result.
              cGraph.commitLayoutToOriginalGraph();
              view.fitContent();
              view.updateView();
            }
          }
        });
      }
    };
    // Assign minimum priority to the layout thread so that the GUI remains 
    // responsive.
    thread.setPriority(Thread.MIN_PRIORITY);
    // Start the layout thread.
    thread.start();
  }
}
When applying the calculated layout to the original graph it is important that no nodes or edges have been added or removed from the graph during the layout process.

Attached is an executable demo program that makes use of the ThreadedLayoutAction. It extends demo.view.ViewActionDemo and should be placed in the yFiles demo package demo.view to function properly.

Resources

Categories this article belongs to:
yFiles for Java > yFiles Layout > Automatic Graph Layout
yFiles for Java > yFiles Layout > Automatic Graph Layout > Organic Layout
yFiles for Java > Other
Applies to:
yFiles for Java 2: 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 2.10, 2.11, 2.12, 2.13, 2.14, 2.15, 2.16, 2.17, 2.18
Keywords:
thread - background - responsive - GUI - layout - invocation - separate - priority