当前位置: 首页 > 知识库问答 >
问题:

JavaFX中的Swing组件

东方俊杰
2023-03-14

我为即将到来的愚蠢问题提前道歉。

是否有JPanel用于javaFX的油漆组件方法的替代品?或者我应该只使用嵌入了Swing的JFXPanel?

例如,我认为时间轴与Swing中的计时器相同,面板/油漆组件对应的是什么?

编辑:例如,我们如何制作一个从x-y坐标到另一个坐标的圆的动画?(当然,不使用TranslateTransition)

我试着用canvas画画,但我不知道如何不断更新画布,比如在Swing中调用repaint()?

共有2个答案

蒋曾笑
2023-03-14

在JavaFX中,只有画布具有GraphicsContext绘图表面。因此,您可以扩展Canvas并添加一个repaint()方法来获取Canas。getGraphicsContext2D()并从中进行自己的绘制。

更进一步,您可以扩展Pane并将叠加的Canvas作为子节点(将Pane和Canvas宽度/高度属性绑定在一起)。然后您有一个支持自定义绘画(并通过画布事件对鼠标事件做出反应)的父组件,就像Swing中的JPanel一样。

司空玮
2023-03-14

这是一个网格示例,它使用简单的绑定自动调整大小。

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Line;

public class Grid {
    private final Pane view = new Pane();

    private final int numColumns ;
    private final int numRows ;

    // arbitrary defaults of 20:
    private final DoubleProperty prefColumnWidth = new SimpleDoubleProperty(20);
    private final DoubleProperty prefRowHeight = new SimpleDoubleProperty(20);

    public Grid(int numColumns, int numRows) {
        this.numColumns = numColumns ;
        this.numRows = numRows ;

        for (int x = 0 ; x <= numColumns ; x++) {
            Line line = new Line();
            line.startXProperty().bind(view.widthProperty().multiply(x).divide(numColumns));
            line.endXProperty().bind(line.startXProperty());
            line.setStartY(0);
            line.endYProperty().bind(view.heightProperty());
            view.getChildren().add(line);
        }

        for (int y = 0 ; y <= numRows ; y++) {
            Line line = new Line();
            line.startYProperty().bind(view.heightProperty().multiply(y).divide(numRows));
            line.endYProperty().bind(line.startYProperty());
            line.setStartX(0);
            line.endXProperty().bind(view.widthProperty());
            view.getChildren().add(line);
        }

        view.prefWidthProperty().bind(prefColumnWidth.multiply(numColumns));
        view.prefHeightProperty().bind(prefRowHeight.multiply(numRows));
    }

    public final DoubleProperty prefColumnWidthProperty() {
        return this.prefColumnWidth;
    }


    public final double getPrefColumnWidth() {
        return this.prefColumnWidthProperty().get();
    }


    public final void setPrefColumnWidth(final double prefColumnWidth) {
        this.prefColumnWidthProperty().set(prefColumnWidth);
    }


    public final DoubleProperty prefRowHeightProperty() {
        return this.prefRowHeight;
    }


    public final double getPrefRowHeight() {
        return this.prefRowHeightProperty().get();
    }


    public final void setPrefRowHeight(final double prefRowHeight) {
        this.prefRowHeightProperty().set(prefRowHeight);
    }

    public Pane getView() {
        return view;
    }

    public int getNumColumns() {
        return numColumns;
    }

    public int getNumRows() {
        return numRows;
    }

}

下面是一个简单的测试:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class GridTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        Grid grid = new Grid(10,10);
        Scene scene = new Scene(grid.getView());
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

有很多不同的方法可以用于此。请注意,上述方法实际上根本不需要子类化,因此您可以编写一个创建窗格的方法:

private Pane createGrid(int numColumns, int numRows) {

    Pane view = new Pane();

    for (int x = 0 ; x <= numColumns ; x++) {
        Line line = new Line();
        line.startXProperty().bind(view.widthProperty().multiply(x).divide(numColumns));
        line.endXProperty().bind(line.startXProperty());
        line.setStartY(0);
        line.endYProperty().bind(view.heightProperty());
        view.getChildren().add(line);
    }

    for (int y = 0 ; y <= numRows ; y++) {
        Line line = new Line();
        line.startYProperty().bind(view.heightProperty().multiply(y).divide(numRows));
        line.endYProperty().bind(line.startYProperty());
        line.setStartX(0);
        line.endXProperty().bind(view.widthProperty());
        view.getChildren().add(line);
    }

    view.setPrefSize(20*numColumns, 20*numRows);
    return view ;
}

或者,如果您想要更接近AWT/Spring的做事方式,可以将区域子类化,使用画布,并覆盖区域。layoutChildren()layoutChildren()方法作为布局过程的一部分被调用(如果区域大小改变,将触发布局过程)。在这篇文章中,我添加了对填充的支持:

import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.Region;

public class Grid extends Region {

    private Canvas canvas ;
    private final int numColumns ;
    private final int numRows ;

    public Grid(int numColumns, int numRows) {
        this.numColumns = numColumns ;
        this.numRows = numRows ;
        canvas = new Canvas();
        getChildren().add(canvas);
    }

    @Override
    protected void layoutChildren() {
        double w = getWidth() - getPadding().getLeft() - getPadding().getRight() ;
        double h = getHeight() - getPadding().getTop() - getPadding().getBottom() ;

        canvas.setWidth(w+1);
        canvas.setHeight(h+1);

        canvas.setLayoutX(getPadding().getLeft());
        canvas.setLayoutY(getPadding().getRight());

        GraphicsContext gc = canvas.getGraphicsContext2D();
        gc.clearRect(0, 0, w, h);

        for (int i = 0 ; i <= numColumns ; i++) {

            // adding 0.5 here centers the line in the physical pixel,
            // making it appear crisper:
            double x = w*i/numColumns + 0.5;

            gc.strokeLine(x, 0, x, h);
        }

        for (int j = 0 ; j <= numRows ; j++) {
            double y = h*j/numRows + 0.5 ;
            gc.strokeLine(0, y, w, y);
        }
    }

    @Override
    protected double computePrefWidth(double height) {
        return 20 * numColumns;
    }

    @Override
    protected double computePrefHeight(double width) {
        return 20 * numRows ;
    }

}

这里有一个测试:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class GridTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        Grid grid = new Grid(10,10);
        grid.setPadding(new Insets(20));
        Scene scene = new Scene(grid, 400, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
 类似资料:
  • 我使用Swing和JavaFX将图像呈现到屏幕上,但得到了意想不到的时间:目标只是在组件上的随机位置呈现1,000,000个图像。为什么JavaFX花了这么长时间? 结果:摆动2.5秒。JavaFX 8.5秒。下面的代码。 在JavaFX中。 用了8.230974466秒 JAVAFX花费了0.02173174秒@10,000个映像,第二次运行花费了0.018200605秒 SWING用了0.13

  • 为了在JavaFX11中创建Jasper报表,我使用了动态报表。我正在Swing节点中加载报表,但Jasper报表只有在我单击stack窗格区域时才会出现,而所有其他组件只有在我悬停在所有这些组件上时才可见。组件和报表内容不是立即加载的,而不是在鼠标悬停时显示的,而报表是在滚动到堆栈窗格上时显示的。 因为这是Java8中的bug,并且似乎已经解决了,但是在Java11中,我也遇到了同样的问题。 更

  • 问题内容: 我刚遇到JavaFX和Swing的怪异之处。 处置已添加到JFrame或JPanel的JavaFX Panel时,重新添加新的JFXPanel将引发IllegalStateException:“已调用Platform.exit”。 就我而言,这是在我删除了一些内部带有JFXPanels的JPanels,然后尝试重新添加它们之后发生的。 问题答案: 幸运的是,我在Oracle论坛上找到了

  • 提前谢了。

  • 我有一个很大的swing应用程序,我想把javafx嵌入其中。我多次尝试这样做(通过遵循oracle教程等),但只有在声明一个新的JFrame以使用JFXPanel组件时才成功。但是,我不想使用新的框架,我想将我的Javafx代码合并到swing应用程序的根JFrame中。 我们可以将javaFX组件嵌入到JPanel而不是JFrame中吗?如果答案是肯定的,为什么我没有成功?

  • 我正在尝试将自定义对象从JPanel拖放到JavaFX场景<为了实现这一点,我创建了一个带有自定义对象和自定义TransferHandler的简单应用程序。在本例中,我的问题是,当我在