Search code examples
javajava-8javafx-8borderpane

Possible Glitch found in JavaFX


Sorry, the title is vague, but I think I found a glitch in JavaFX BorderPane class, but I'm not positive. So what I'm doing is running this method inside a javaFx Concurrent Task object which is inside a Thread. This method works all the way up until it hits the print statements. It prints out 1 and then doesn't move past the root.setCenter method. If I comment out that code it moves on, otherwise it gets stuck on it like it's in a infinite loop. It is important to note that the root (a boderpane object) is locally stored within the JavaFX main Thread. Thanks for any suggestions.

  // will be used to store all the sites we still need to visit so we can do
  // a breadth first graph traversal of the hostsite
  Queue<URL> unvistedURLs = new LinkedList<>();
  LinkedList<Text> currentLevelText = new LinkedList<>();
  Queue<URL> levelCheckpoints = new LinkedList<>();
  int currentLevelHieght = 0;

  // the origional host
  String hostName = origin.getHost();

  // temporary objects
  HTMLLinks endHTMLLinks = null;
  try
  {
     endHTMLLinks = new HTMLLinks(origin);
  }
  catch (IOException e1)
  {
     // TODO Auto-generated catch block
     e1.printStackTrace();
  }

  HostSiteInfo hostSiteInfo = new HostSiteInfo();
  URL currentURL;
  Group displayArea = new Group();

  System.out.println(1);
  root.setCenter(displayArea);
  System.out.println(2);
  // imediatley input the host as a site we need to visit
  unvistedURLs.add(origin);
  levelCheckpoints.offer(origin);


@Override
public void start(Stage primaryStage)
{
  try
  {
     final BorderPane root = new BorderPane();
     Scene scene = new Scene(root, 1600, 1000);

     @SuppressWarnings("rawtypes")
     Thread renderThread = new Thread(new Task(){

        @Override
        protected Object call() throws Exception
        {
           try
           {

              WebSpider.traverseURLs(root,
                    new URL("http://www.georgefox.edu/"),
                    new PrintStream(System.out));
           }
           catch (MalformedURLException e)
           {
              // TODO Auto-generated catch block
              e.printStackTrace();
           }

           return null;
        }});

     renderThread.setDaemon(true);
     renderThread.start();

The root of the JavaFx app is initialized in the this start method.


Solution

  • Assuming root.setCenter is called inside the Task (this is unclear from your code), you are getting an exception because you are trying to modify the scene graph from a thread other than the JavaFX UI thread. Since this is done inside a Task, the exception is caught by the task and you end up not seeing it.

    To solve this problem replace root.setCenter(displayArea) with

    Platform.runLater(() -> root.cetCenter(displayArea)); 
    

    See Platform#runLater.

    To be able to catch such problems, it is probably best to set an onFailed handler to your Task:

    Task<Void> myTask = new Task<>() {
        ...
    }
    myTask.setOnFailed(workerStateEvent -> {
         System.out.println("Something wrong happened...");
         myTask.getException().printStackTrace();
         // Or handle the problem however suits your application. 
    });