gpt4 book ai didi

java - 如何在javafx中嵌入PApplet?

转载 作者:行者123 更新时间:2023-12-02 05:01:17 26 4
gpt4 key购买 nike

所以我让我的处理代码在java中工作。但现在我想将它嵌入到我的 GUI 的 JavaFX 中。我怎样才能这样做呢?我尝试使用以下代码,但它似乎不起作用。

 package testprocessing;
import javafx.application.Application;
import javafx.embed.swing.SwingNode;
import javafx.scene.*;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

import javax.swing.JApplet;
import javax.swing.SwingUtilities;
import java.awt.Dimension;

import java.util.concurrent.*;
import processing.core.*;

public class JavaFxApplet extends Application {
private PApplet applet = new MyProcessingSketch();
private Dimension appletSize;

@Override public void init() throws ExecutionException, InterruptedException {
applet.init();

FutureTask<Dimension> sizingTask = new FutureTask<>(() ->
applet.getRootPane().getPreferredSize()
);
SwingUtilities.invokeLater(sizingTask);
appletSize = sizingTask.get();
}

@Override public void start(Stage stage) {
final SwingNode swingNode = new SwingNode();
SwingUtilities.invokeLater(() ->
swingNode.setContent(applet.getRootPane())
);

stage.setScene(
new Scene(
new Group(swingNode),
appletSize.getWidth(), appletSize.getHeight(),
Color.BLACK
)
);
stage.show();
}

@Override public void stop() {
applet.stop();
applet.destroy();
}

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

我在 getRootPane() 处遇到错误。你能建议一个替代方案吗?

最佳答案

背景

Processing 3 中引入了一种 JavaFX 渲染模式,可以将 JavaFX 包含在我们的草图中。我们可以在 JavaFX 模式下初始化 PApplet 类构造的窗口时修改它,在其中添加新的 JavaFX 元素,而不是从头开始创建我们自己的 JavaFX 窗口,然后将草图嵌入其中。

在 JavaFX 模式下初始化期间,PApplet 类创建 javafx.scene.canvas.Canvas对象并将其作为子项添加到 javafx.scene.layout.StackPane目的。然后,一个javafx.scene.Scene对象是用 stackPane 对象作为参数构造的。最后,PApplet 类创建一个 javafx.stage.Stage对象并将其场景设置为 scene 对象,为我们提供 PApplet 实例 - 草图。

因此,就 JavaFX 元素而言,PApplet 窗口使用以下层次结构中的四个元素进行初始化: <i>Stage > Scene > StackPane > Canvas</i> ,其中 Canvas 是草图的图形 Canvas (即处理绘制的对象)。

要创建我们自己的 GUI,我们可以添加任何 javafx.scene.Node对象(这是 JavaFX 图形元素的父类(super class))到 stackPane 对象。或者,您可以构建一个新的场景,向其中添加处理 Canvas ,并替换舞台的现有场景

<小时/>

什么似乎不起作用

如果不指定渲染模式,Processing默认为JAVA2D模式。在此模式下,PApplet 类使用 java.awt 创建一个 PApplet 实例。 Canvas 和窗口的版本(分别为 java.awt.Canvasjava.awt.Frame)。理论上,可以转换java.awt.Framejavax.swing.JFrame ,将其嵌入 javafx.embed.swing.SwingNode对象,最后将其添加到 JavaFX 阶段。但是,我没能让它发挥作用。

还有P2D & P3D模式。在这些模式下, Canvas 是 com.jogamp.newt.opengl.GLWindow目的。再次,我尝试在 com.jogamp.opengl.awt.GLJPanel 的帮助下将其嵌入到 Swing 节点中。 ,但尚未证明是成功的。

<小时/>

实现

在Processing's FX2D中初始化您的草图调用 size() 中的渲染模式:

size([width], [height], <b>FX2D</b>);

然后我们可以通过重复转换公开初始化期间创建的四个 JavaFX 元素:

final PSurfaceFX FXSurface = (PSurfaceFX) surface;

final Canvas canvas = (Canvas) FXSurface.getNative();
final StackPane stackPane = (StackPane) canvas.getParent();
final Scene scene = canvas.getScene();
final Stage stage = (Stage) canvas.getScene().getWindow();

我们现在可以选择如何添加 JavaFX 元素:

1) 添加到现有的 stackPane

我们可以使用以下方法将 JavaFX 元素( javafx.scene.Node 对象)添加到初始化期间创建的 stackPane 中:

stackPane.getChildren().add(Node node);

2) 创建新场景(推荐)

或者(推荐,除非您想要 stackPane 作为顶级对齐器),我们可以创建一个新的场景对象(而不是使用 scenestackPane 对象在初始化期间创建的)并向其中添加 JavaFX 元素。

Scene newscene = new Scene(new Group(canvas)); // simple group containing only the Processing canvas
stage.setScene(Scene scene);

在初始化期间,canvas的尺寸会绑定(bind)到stackPane的尺寸。如果我们希望在运行时更改窗口内处理 Canvas 的大小,则必须包括以下内容:

canvas.widthProperty().unbind();
canvas.heightProperty().unbind();

现在我们可以自由调用canvas.setHeight()canvas.setWidth()在 JavaFX 窗口(舞台)内调整处理 Canvas 的大小。

示例

让我们添加一个 javafx.scene.control.MenuBar到 window 。请注意,我正在 initSurface() 中初始化我们的 JavaFX 元素。方法而不是在setup()内这样做方法,因为这样比较安全。

在此示例中,stackPane 被替换为 javafx.scene.layout.VBox首先,让菜单栏位于 Canvas 之上;其次,确保启动时舞台的高度正确(菜单栏高度与 Canvas 高度之和) .

@Override
public void settings() {
size(500, 500, FX2D);
}

@Override
protected PSurface initSurface() {

PSurface surface = super.initSurface();

final PSurfaceFX FXSurface = (PSurfaceFX) surface;
final Canvas canvas = (Canvas) FXSurface.getNative(); // canvas is the processing drawing
final Stage stage = (Stage) canvas.getScene().getWindow(); // stage is the window

stage.setTitle("Processing/JavaFX Example");
canvas.widthProperty().unbind();
canvas.heightProperty().unbind();

final MenuItem menuItem1 = new MenuItem("Fill green");
menuItem1.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
noLoop();
background(0, 255, 0); // Fills the canvas green on click
}
});

final MenuItem menuItem2 = new MenuItem("Exit");
menuItem2.setOnAction(actionEvent -> exit()); // Exit PApplet on click

final Menu menu = new Menu("Menu");
menu.getItems().add(menuItem1);
menu.getItems().add(menuItem2);

final MenuBar menuBar = new MenuBar();
menuBar.getMenus().add(menu);

final VBox vBox = new VBox(menuBar, canvas); // Menubar will sit on top of canvas
final Scene newscene = new Scene(vBox); // Create a scene from the elements
Platform.runLater(new Runnable() {
@Override
public void run() {
stage.setScene(newscene); // Replace the stage's scene with our new one.
}
});
return surface;
}

@Override
public void draw() {
background(50);
fill(0, 255, 0);
strokeWeight(5);
stroke(255, 5, 5);
line(0, 0, width, 0); // shows us that window is the correct dimensions
line(0, height, width, height); // shows us that window is the correct dimensions
noStroke();
ellipse(100, 100, 200, 200);
fill(255, 0, 0);
ellipse(100, 200, 200, 200);
fill(0, 0, 255);
ellipse(100, 300, 200, 200);
}

结果

Result

关于java - 如何在javafx中嵌入PApplet?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28266274/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com