I've got a class that displays a graph using Zest that can be run on its own since it has a main method. However, I'd like to that main method to be run when I select a button in another shell. The problem is that I get an Invalid Thread Access SWTException when I just call the main function from the selectionListener of the button. From my understanding, the Display object(s) used in both cases is causing trouble. Looking at similar posts here hasn't helped me either.. Could someone please point me in the right direction? Thanks. *I've added short testeable code that illustrates my problem. import org.eclipse.swt.widgets.Display;
public class CallGraph {
protected Shell shell;
/**
* Launch the application.
* @param args
*/
public static void main(String[] args) {
try {
CallGraph window = new CallGraph();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Open the window.
*/
public void open() {
Display display = Display.getDefault();
createContents();
shell.open();
shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
/**
* Create contents of the window.
*/
protected void createContents() {
shell = new Shell();
shell.setSize(450, 300);
shell.setText("SWT Application");
shell.setLayout(new GridLayout(6, false));
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
Button btnGetGraph = new Button(shell, SWT.NONE);
btnGetGraph.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
RadialLayoutExample.main(null);
}
});
btnGetGraph.setText("Get Graph");
}
}
The below class has the button to call the main method of above class.
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.zest.core.widgets.Graph;
import org.eclipse.zest.core.widgets.GraphConnection;
import org.eclipse.zest.core.widgets.GraphNode;
//import org.eclipse.zest.layout.algorithms.RadialLayoutAlgorithm;
//import org.eclipse.zest.layout.interfaces.LayoutAlgorithm;
public class RadialLayoutExample {
public static void main(String[] args) {
// Create the shell
Display d = new Display();
Shell shell = new Shell(d);
shell.setText("GraphSnippet1");
shell.setLayout(new FillLayout());
shell.setSize(500, 500);
final Graph g = new Graph(shell, SWT.NONE);
g.setSize(500, 500);
GraphNode root = new GraphNode(g, SWT.NONE, "Root");
for (int i = 0; i < 3; i++) {
GraphNode n = new GraphNode(g, SWT.NONE, "1 - " + i);
for (int j = 0; j < 3; j++) {
GraphNode n2 = new GraphNode(g, SWT.NONE, "2 - " + j);
new GraphConnection(g, SWT.NONE, n, n2).setWeight(-1);
}
new GraphConnection(g, SWT.NONE, root, n);
//final org.eclipse.zest.layouts.algorithms.RadialLayoutAlgorithm layoutAlgorithm = new org.eclipse.zest.layouts.algorithms.RadialLayoutAlgorithm();
final org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm layoutAlgorithm = new org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm();
g.setLayoutAlgorithm(layoutAlgorithm, true);
shell.open();
while (!shell.isDisposed()) {
while (!d.readAndDispatch()) {
d.sleep();
}
}
}
}
}
Change the data type of the argument received by the main method from String to Display. When calling the main method, pass the existing class's display along as an argument. The reasoning behind this is that for each application only one Display object is required as it functions as a link between your application and the underlying OS. Creating more than one messes with the threads involved. * Thanks to @greg-449's comment for pointing me in the right direction.