有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在javafx中嵌入PApplet?

所以我用java编写了处理代码。但现在我想把它嵌入JavaFX中,用于我的GUI。我该怎么做? 我尝试使用以下代码,但似乎不起作用

 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()上遇到错误。你能推荐一个替代方案吗


共 (2) 个答案

  1. # 1 楼答案

    为什么要获取小程序的根窗格?只需将小程序添加到JPanel,然后将JPanel添加到SwingNode:

    JPanel panel = new JPanel();
    panel.add(applet);
    swingNode.setContent(panel)
    
  2. # 2 楼答案

    背景

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

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

    因此,就JavaFX元素而言,PApplet窗口由以下层次结构中的四个元素初始化:Stage > Scene > StackPane > Canvas,其中画布是草图的图形画布(即处理绘制到的对象)

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


    什么似乎不起作用

    在不指定渲染模式的情况下,处理默认为JAVA2D模式。在这种模式下,PApplet类创建一个PApplet实例,其中包含画布和窗口的java.awt版本(分别是java.awt.Canvasjava.awt.Frame)。理论上,可以将java.awt.Frame强制转换为javax.swing.JFrame,将其嵌入javafx.embed.swing.SwingNode对象,最后将其添加到JavaFX阶段。然而,我一直没能让它发挥作用

    还有P2D&P3D模式。在这些模式中,画布是com.jogamp.newt.opengl.GLWindow对象。我再次尝试在com.jogamp.opengl.awt.GLJPanel的帮助下将其嵌入到Swing节点中,但没有成功


    实施

    在调用size()的过程FX2D渲染模式下初始化草图:

    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();
    

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

    1)添加到现有的堆栈窗格

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

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

    2)创建新场景(推荐)

    或者(建议使用stackPane,除非您希望将其作为顶级对齐器),我们可以创建一个新的场景对象(而不是使用初始化过程中创建的场景stackPane对象),并向其添加JavaFX元素

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

    在初始化过程中,画布的维度绑定到堆栈窗格的维度。如果我们希望在运行时更改窗口内处理画布的大小,我们必须包括以下内容:

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

    现在,我们可以自由调用canvas.setHeight()canvas.setWidth()来调整JavaFX窗口(后台)中处理画布的大小

    范例

    让我们在窗口中添加一个javafx.scene.control.MenuBar。注意,我在initSurface()方法中初始化JavaFX元素,而不是在setup()方法中初始化,因为这样更安全

    在本例中,stackPane被替换为javafx.scene.layout.VBox,首先是使菜单栏位于画布的顶部,其次是确保stage在启动时是正确的高度(菜单栏高度和画布高度之和)

    @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