Reputation: 2030
I'm developing a JavaFX desktop application. In it I want to display some java 3D objects.
The way to do this, as far as I know, is using JavaFX's SwingNode. Java 3d has to be integrated in a Swing component too. So it's a two-step process.
Integrating Java 3D objects with Java Swing
Complete and minimal example composed of the panel I intend to reuse in the FX app and a JFrame that shows it works:
import java.awt.BorderLayout;
import javax.swing.JFrame;
public class JFrameWithCanvas3D extends JFrame {
public JFrameWithCanvas3D() {
super("Swing JFrame Wraps Canvas3D");
setLayout(new BorderLayout());
BallPanel panel = new BallPanel();
add(panel, BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public static void main(String[] args) {
System.setProperty("sun.awt.noerasebackground", "true");
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@SuppressWarnings("unused")
@Override
public void run() {
new JFrameWithCanvas3D();
}
});
}
}
public class BallPanel extends JPanel {
public BallPanel() {
setLayout(new BorderLayout());
setPreferredSize(new Dimension(500, 500));
add(makeCanvas());
}
private static Canvas3D makeCanvas() {
BranchGroup group = new BranchGroup();
group.addChild(makeLight());
group.addChild(new Sphere(5));
Canvas3D canvas3D = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
SimpleUniverse universe = new SimpleUniverse(canvas3D);
Transform3D viewTransform = new Transform3D();
viewTransform.setTranslation(new Vector3d(0, 0, 20)); //move "back" a little
universe.getViewingPlatform().getViewPlatformTransform().setTransform(viewTransform);
universe.addBranchGraph(group);
return canvas3D;
}
private static DirectionalLight makeLight() {
DirectionalLight light = new DirectionalLight(new Color3f(Color.WHITE), new Vector3f(-1.0f, -1.0f, -1.0f));
light.setInfluencingBounds(new BoundingSphere(new Point3d(0, 0, 0), 100));
return light;
}
}
Integrating the BallPanel in the JavaFX app
public class FXAppWithSwingPanel extends Application {
@Override
public void start(Stage stage) {
final SwingNode swingNode = new SwingNode();
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.setPreferredSize(new Dimension(450, 450));
panel.add(new BallPanel(), BorderLayout.CENTER);
swingNode.setContent(panel);
Pane pane = new Pane();
pane.getChildren().add(swingNode);
stage.setScene(new Scene(pane, 500, 500));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
All I see is a gray background where the sphere should be. I've tried a few different variations with no luck. Couldn't find anything online about this particular integration between Java 3D classes and JavaFX.
I know JavaFX has 3D graphics but I don't like them (at all).
Related, unresolved, question:
How Can I embed java3d's Canvas3d in javafx layout?
Upvotes: 1
Views: 1325
Reputation: 2030
I finally managed to make it work using JCanvas3D. Credit for the suggestion goes to @gouessej. Many thanks.
Here is the new makeCanvas
method:
private void makeCanvas() {
GraphicsConfigTemplate3D gCT = new GraphicsConfigTemplate3D();
JCanvas3D jCanvas3D = new JCanvas3D(gCT);
Dimension canvasDim = new Dimension(400, 400);
jCanvas3D.setPreferredSize(canvasDim);
jCanvas3D.setSize(canvasDim);
add(jCanvas3D, BorderLayout.CENTER);
Canvas3D canvas3D = jCanvas3D.getOffscreenCanvas3D();
View view = new View();
view.setPhysicalBody(new PhysicalBody());
view.setPhysicalEnvironment(new PhysicalEnvironment());
view.addCanvas3D(canvas3D);
ViewPlatform vp = new ViewPlatform();
view.attachViewPlatform(vp);
Transform3D viewTransform = new Transform3D();
viewTransform.setTranslation(new Vector3d(0, 0, 20)); //move "back" a little
TransformGroup viewTG = new TransformGroup();
viewTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
viewTG.setTransform(viewTransform);
viewTG.addChild(vp);
viewTG.addChild(makeLight());
viewTG.addChild(new Sphere(5));
BranchGroup group = new BranchGroup();
group.addChild(viewTG);
group.addChild(makeLight());
group.addChild(new Sphere(5));
VirtualUniverse vu = new VirtualUniverse();
Locale locale = new Locale(vu);
locale.addBranchGraph(group);
}
Also, as James_D points out in the comments, Canvas3D
was not the way to go as it cannot be correctly rendered in a JavaFX
SwingNode
because it is a heavyweight component.
The SwingNode javadoc confirms it:
The hierarchy of components contained in the JComponent instance should not contain any heavyweight components, otherwise SwingNode may fail to paint it.
Upvotes: 1
Reputation: 10650
If these two sentences "I'm developing a JavaFX desktop application. In it I want to display some java 3D objects." are really the essence of what you are asking here, then you are completely on the wrong track. JavaFX supports 3D shapes natively, so unless you have very specific requirements there is no need for any Canvas3D and embedding any Swing.
I just see that you have said that you know the JavaFX 3D graphics but you don't like it. Could you be a bit more specific about what you don't like?
Upvotes: 0