JavaFX场景中的Java Processing 3 PAplet作为FXNode

Jan*_*rný 3 java processing user-interface javafx fractals

我正在尝试制作一个用于视觉分析分形集的程序。我选择“处理3”作为图形库,并选择JavaFX作为用户界面。有一些当前状态的屏幕截图:

我的GUI:

JavaFX Scene Builder

有启动器代码:

import Graphics.Canvas2D;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import processing.core.PGraphics;

import java.io.IOException;

public class Launcher extends Application {
    private static Stage primaryStage;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        Parent root = loadFXML("MainUI.fxml");
        Scene scene = new Scene(root, 500, 400);
        primaryStage.setTitle("Fractal Analyzer");
        primaryStage.setScene(scene);
        primaryStage.show();
        primaryStage.setMaximized(true);

        Launcher.primaryStage = primaryStage;
    }

    @Override
    public void init() {

    }

    @Override
    public void stop() {
        System.exit(0);
    }

    public static Stage getPrimaryStage() {
        return primaryStage;
    }

    public  void setCanvas(Canvas2D canvas){

    }



    private Parent loadFXML(String path) {
        try {
            return FXMLLoader.load(getClass().getResource(path));
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.exit(1);
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

测试分形PAplet:

处理窗口

此PAplet有一个代码:

package Fractal;

import processing.core.PApplet;

public class SirpenskiTriangle extends PApplet {

    public static void main(String[] args) {
        PApplet.main("Fractal.SirpenskiTriangle");
    }

    public void settings() {
        size(640, 640);
        smooth();
        if (frame != null) {
            frame.setResizable(true);
        }
    }

    public void draw() {
        drawTriangle(new Position(300, 20), new Position(620, 620), new Position(20, 620), 0);
        noLoop();
        scale(10f);
    }

    public void setup(){}

    public void drawTriangle(Position top, Position right, Position left, int depth) {
        if (depth > 10) return;

        line(top.x, top.y, right.x, right.y);
        line(right.x, right.y, left.x, left.y);
        line(left.x, left.y, top.x, top.y);

        drawTriangle(top, top.middleWith(right), top.middleWith(left), depth + 1);
        drawTriangle(top.middleWith(left), left.middleWith(right), left, depth + 1);
        drawTriangle(top.middleWith(right), right, left.middleWith(right), depth + 1);
    }

    class Position {
        final float x;
        final float y;

        Position(float x, float y) {
            this.x = x;
            this.y = y;
        }

        Position middleWith(Position other) {
            return new Position((x + other.x) / 2, (y + other.y) / 2);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有什么方法可以将处理PAplet放入画布或类似的JavaFX场景吗?

我希望它可以这样工作,但是此代码无效: 例

mic*_*cle 5

您必须下载经过稍微修改的core.jar才能正常工作,在这里我将PSurfaceFXand PGraphicsFX2D类的一些成员的可见性从Protected更改为Public... extends Application所做的更改使我们可以从我们自己的类中启动JavaFX ,同时保留对Processing启动过程中需要设置的成员的访问权限。

当使用的JDK在Java 8之上时,处理3在FX2D模式下崩溃,因此我也为8+作了工作版本,因为FXML文件通常至少需要Java 9才能工作。

在此示例中,这是我正在使用的FXML文件:

在此处输入图片说明

将修改后的core.jar添加到项目的类路径中,initSurface()并使用以下代码片段在PApplet类中进行覆盖。使用此代码,我们绕过了PApplet的调用initFrame()-在这里处理将创建自己的JavaFX阶段,我们不希望这样做。

@Override
protected PSurface initSurface() {
    g = createPrimaryGraphics();
    PSurface genericSurface = g.createSurface();
    PSurfaceFX fxSurface = (PSurfaceFX) genericSurface;

    fxSurface.sketch = this;

    Launcher.surface = fxSurface;

    new Thread(new Runnable() {
        public void run() {
            Application.launch(Launcher.class);
        }
    }).start();

    while (fxSurface.stage == null) {
        try {
            Thread.sleep(5);
        } catch (InterruptedException e) {
        }
    }

    this.surface = fxSurface;
    return fxSurface;
}
Run Code Online (Sandbox Code Playgroud)

将PApplet的渲染模式设置为FX2D,如下所示:

@Override
public void settings() {
    size(0, 0, FX2D);
}
Run Code Online (Sandbox Code Playgroud)

将以下内容或类似内容放入Launcher类。在此示例中,我手动找到了要将画布对象添加到的节点。有更好的,更具编程性的方法(例如,使用所需节点的fx:id的.lookup())。我还将画布的尺寸绑定到其父对象的尺寸,因此当拖动将“ 窗格和“ 视图”窗格分开的除数时,画布将相应地调整大小。

public class Launcher extends Application {

    public static PSurfaceFX surface;

    @Override
    public void start(Stage primaryStage) throws Exception {

        Canvas canvas = (Canvas) surface.getNative(); // boilerplate
        GraphicsContext graphicsContext = canvas.getGraphicsContext2D(); // boilerplate
        surface.fx.context = graphicsContext; // boilerplate

        primaryStage.setTitle("FXML/Processing");

        VBox root = FXMLLoader.load(new File("c:/Users/Mike/desktop/test.fxml").toURI().toURL());
        SplitPane pane = (SplitPane) root.getChildren().get(1); // Manually get the item I want to add canvas to
        AnchorPane pane2 = (AnchorPane) pane.getItems().get(0); // Manually get the item I want to add canvas to
        pane2.getChildren().add(canvas); // Manually get the item I want to add canvas to

        canvas.widthProperty().bind(pane2.widthProperty());
        canvas.heightProperty().bind(pane2.heightProperty());

        Scene scene = new Scene(root, 800, 800);
        primaryStage.setScene(scene);
        primaryStage.show();

        surface.stage = primaryStage; // boilerplate
    }
}
Run Code Online (Sandbox Code Playgroud)

结果如下:

在此处输入图片说明