Classpath resolution with hierarchical custom Java

2019-03-17 00:42发布

I'm creating custom components using FXML. The custom components are designed in a hierarchical fashion.

When I design a custom component B that uses another custom component A, a classpath problem dialog pops up in scenebuilder and I simply fix this by setting the appropriate classpath.

However when I create three components, say C containing B containing A, and try to open top-level component C in Scenebuilder it fails. It asks me for classpaths which I duly specify. It finds B but does not find A.

The classpath, FXML and the code is correct as the application is able to execute properly. Only Scenebuilder is having problems.

How should one open hierarchical custom component with Scenebuilder?

Any reference to an example with hierarchical component definitions using FXML would be greatly appreciated and get a bounty of 50 points. (only 3 levels needed)

1条回答
叼着烟拽天下
2楼-- · 2019-03-17 01:35

Someone named David did answer your question on the forum. For legacy purpose I post it here.

There is a problem with the classloader in Scene Builder for custom components. When you load a FXML file in SceneBuilder: it uses a FXMLLoader with its own classloader. In order to load custom components which use their own FXMLLoader to load other custom components, it is necessary to make all FXMLLoader use the same classloader. As David said on the forum, you can achieve that by adding this code in your custom component.

public class CustomC extends VBox {
    public CustomC() {
        init();
    }

    private void init() {
        FXMLLoader loader = new FXMLLoader();
        loader.setRoot(this);
        loader.setLocation(this.getClass().getResource("CustomC.fxml"));

        // Make sure to load "CustomC.fxml" with the same classloader that
        // was used to load CustomC class. 
        loader.setClassLoader(this.getClass().getClassLoader());

        try {
           final Node root = (Node)loader.load();
           assert root == this;
        } catch (IOException ex) {
           throw new IllegalStateException(ex);
        }
    }
}

If you want to externalize this code in a class, it is important to put this class in the same jar as your custom components: you cannot put it in a external jar (at least for now).

查看更多
登录 后发表回答