sj6*_*j66 3 java processing user-interface netbeans javafx
所以我让我的处理代码在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);
}
}
Run Code Online (Sandbox Code Playgroud)
我在 getRootPane() 处收到错误。你能建议一个替代方案吗?
Process 3中引入了 JavaFX 渲染模式,可以将 JavaFX 包含在我们的草图中。我们可以修改 PApplet 类在 JavaFX 模式下初始化时构造的窗口,在其中添加新的 JavaFX 元素,而不是从头开始创建我们自己的 JavaFX 窗口,然后将草图嵌入其中。
在 JavaFX 模式下初始化期间,PApplet 类创建一个javafx.scene.canvas.Canvas对象并将其作为子对象添加到javafx.scene.layout.StackPane对象中。然后,以stackPane对象作为参数javafx.scene.Scene构造一个对象。最后,PApplet 类创建一个对象并将其场景设置为场景对象,为我们提供 PApplet 实例 - 草图。javafx.stage.Stage
因此,就 JavaFX 元素而言,PApplet 窗口使用以下层次结构中的四个元素进行初始化:Stage > Scene > StackPane > Canvas,其中画布是草图的图形画布(即,Processing 绘制到的对象)。
要创建我们自己的 GUI,我们可以将任何javafx.scene.Node对象(这是 JavaFX 图形元素的超类)添加到stackPane对象。或者,您可以构造一个新的Scene,向其中添加处理的画布,然后替换Stage的现有Scene。
如果不指定渲染模式,Processing默认为JAVA2Dmode。在此模式下,PApplet 类创建一个带有java.awt画布和窗口版本(分别为 ajava.awt.Canvas和java.awt.Frame)的 PApplet 实例。理论上,可以将 转换java.awt.Frame为 a javax.swing.JFrame,将其嵌入到javafx.embed.swing.SwingNode对象中,最后将其添加到 JavaFX 阶段。但是,我无法让它发挥作用。
还有P2D&P3D模式。在这些模式下,画布是一个 com.jogamp.newt.opengl.GLWindow对象。同样,我尝试在 的帮助下将其嵌入到 Swing Node 中com.jogamp.opengl.awt.GLJPanel,但事实证明它并不成功。
FX2D在调用中以处理渲染模式初始化草图size():
size([width], [height], FX2D);
然后,我们可以通过重复转换公开初始化期间创建的四个 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();
Run Code Online (Sandbox Code Playgroud)
我们现在可以选择如何添加 JavaFX 元素:
1)添加到现有的stackPane
我们可以使用以下方法将 JavaFX 元素(javafx.scene.Node对象)添加到初始化期间创建的stackPane中:
stackPane.getChildren().add(Node node);
Run Code Online (Sandbox Code Playgroud)
2)创建新场景(推荐)
或者(推荐,除非您想要 stackPane 作为顶级对齐器),我们可以创建一个新的场景对象(而不是使用初始化期间创建的场景和stackPane对象)并向其中添加 JavaFX 元素。
Scene newscene = new Scene(new Group(canvas)); // simple group containing only the Processing canvas
stage.setScene(Scene scene);
Run Code Online (Sandbox Code Playgroud)
在初始化期间,画布的尺寸绑定到stackPane的尺寸。如果我们希望在运行时更改窗口内处理画布的大小,则必须包括以下内容:
canvas.widthProperty().unbind();
canvas.heightProperty().unbind();
Run Code Online (Sandbox Code Playgroud)
现在我们可以在 JavaFX 窗口(舞台)内自由调用canvas.setHeight()和调整处理画布的大小。canvas.setWidth()
让我们javafx.scene.control.MenuBar向窗口添加一个。请注意,我是在方法内初始化 JavaFX 元素,initSurface()而不是在方法内初始化setup(),因为这样更安全。
在此示例中,stackPane被替换为javafx.scene.layout.VBox,首先,以便菜单栏位于画布顶部,其次,确保舞台在启动时具有正确的高度(菜单栏高度和画布高度的总和)。
@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);
}
Run Code Online (Sandbox Code Playgroud)
结果