How to display text in Node via JFX?

I was told that I can use JFX text rendering inside jme; so I’d like to have a string with a ttf font rendered in a Node. How should I do that? Thanks!

By using the jfx library, and adding a Text object there.
Using css+ressources you can simply change the font as wanted, or use the buildin ones.
Take a look at scenebuilder to see the available ones.

1 Like

You mean this
http://docs.oracle.com/javafx/2/api/javafx/scene/text/Text.html
and this
http://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html#introexamples
?

Yes, combined with this

So I did this on my init:

PlatformImpl.startup(new Runnable() {
   @Override public void run() {
   }
});

Then I want to do something like this appstate:

public class JFXAppState extends BaseAppState {

    @Override
    protected void initialize(Application app) {
        Scene scene=new Scene(guiNode);
        Text text = new Text();
        text.setFont(new Font(20));
        text.setText("First row\nSecond row");
        scene.add(text);
    }

    @Override
    protected void cleanup(Application aplctn) {
    }

    @Override
    protected void enable() {
    }

    @Override
    protected void disable() {
    }
}

Tried to check the thread above, but there are almost 300 posts! : :scream:

Look at the examples at github, they show how to use this.

I get an exception caused by this:

Caused by: java.lang.ClassNotFoundException: com.jme3x.jfx.Testcontroller
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)

Relevant question: is jfx font rendering going to noticeably affect performance of my game?

It should not really affect performance as long as you have a cpu core to spare. All jfx work is done on other thread and synchronization between two is done on purpose in the way favoring jme rendering (so we rather miss updating jfx window for one frame then block jme from working).

Said that, all these things have to be rendered. You will pay a cost of drawing transparent quad with texture which is continously propagating from cpu world to gpu world (if you do any updates). But given current hardware, it should be completely neglible (and might turn out to be comparable to any other solution for displaying text).

Sounds like your Project setup is not correct, wich ide do you use and how did you set it up?

I’m using Jmonkey 3.0.10, with the lib jfx-1.133.2015-01-02_115420-8ebb0c0.jar

Please note that I’m running the MovieAppState (via jfx) without problems.

Here’s my complete source:

import org.lwjgl.opengl.Display;

import com.jme3.app.SimpleApplication;
import com.jme3.math.ColorRGBA;
import com.jme3.system.AppSettings;
import com.jme3x.jfx.FXMLHud;
import com.jme3x.jfx.cursor.proton.ProtonCursorProvider;
import com.jme3x.jfx.FXMLWindow;
import com.jme3x.jfx.GuiManager;

public class Test extends SimpleApplication {
    private static boolean    assertionsEnabled;

    public static void main(final String[] args) {
        assert Test.enabled();
        if (!Test.assertionsEnabled) {
            throw new RuntimeException("Assertions must be enabled (vm args -ea");
        }
        final AppSettings settings = new AppSettings(true);
        // settings.setGammaCorrection(true);
        final Test t = new Test();
        t.setSettings(settings);
        t.start();
    }

    private static boolean enabled() {
        Test.assertionsEnabled = true;
        return true;
    }

    @Override
    public void simpleInitApp() {

        this.setPauseOnLostFocus(false);
        this.flyCam.setDragToRotate(true);
        this.viewPort.setBackgroundColor(ColorRGBA.Red);

        final GuiManager testguiManager = new GuiManager(this.guiNode, this.assetManager, this, true, new ProtonCursorProvider(this, this.assetManager, this.inputManager));
        /**
         * 2d gui, use the default input provider
         */
        this.inputManager.addRawInputListener(testguiManager.getInputRedirector());

        try {
            Thread.sleep(1000);
        } catch (final InterruptedException e) {
            e.printStackTrace();
        }
        final FXMLHud testhud = new FXMLHud("com/jme3x/jfx/loading_screen.fxml");
        testhud.precache();
        testguiManager.attachHudAsync(testhud);

        final FXMLWindow testwindow = new FXMLWindow("com/jme3x/jfx/loading_screen.fxml");
        testwindow.externalizeDoNotCallUglyAPI();//xternalized().set(true);
        testwindow.precache();
        testwindow.setTitleAsync("TestTitle");
        testguiManager.attachHudAsync(testwindow);

        Display.setResizable(true);
    }

    @Override
    public void simpleUpdate(final float tpf) {
        if (Display.wasResized()) {
            // keep settings in sync with the actual Display
            int w = Display.getWidth();
            int h = Display.getHeight();
            if (w < 2) {
                w = 2;
            }
            if (h < 2) {
                h = 2;
            }
            this.settings.setWidth(Display.getWidth());
            this.settings.setHeight(Display.getHeight());
            this.reshape(this.settings.getWidth(), this.settings.getHeight());
        }
    }
}

Hm, can you post the full exception? Also some more details about your system, like os, gpu, java version ect.

Hm,

are you 100% sure that com.jme3x.jfx.Testcontroller is in the classpath?
eg what happens if you just add “new com.jme3x.jfx.Testcontroller()” to the main method?

You’re right, “cannot find symbol”!

So what am I missing, exactly?

It must be the src/test/java .
The class should be there if everything is correct,
basically you should have a folder looking similar to this one

I just wonder how it then finds the Test.java in the same folder? or did you copy past it somewhere else?
If so you might need all files in there depending on the actual testcase.

Some progress!
Now I have this:

java.lang.NoClassDefFoundError: jfxtras/scene/layout/HBox

The Test is copypasted from the repository.

You use a pretty old version,

your release seems to be over a month outdated, the jfxtras is no longer used. By the current version.

1 Like

It works! :smile:
Bleeding edge indeed… :wink:

While I managed to run the demo, I find myself unable to hack my way toward my goal…
Editing the fxml gives me errors, and the code looks rather cryptic for a javafx n00b like myself. :frowning:

Oh well, thanks anyway!

install Scenebuilder for fxml editing, no need to do by hand.
Or do it swing style all programatically, works as well.

(Tho both are non jme specific, but just normal jfx stuff)