【问题标题】:JavaFX resize canvas in fxmlJavaFX 在 fxml 中调整画布大小
【发布时间】:2015-11-05 00:26:05
【问题描述】:

我正在尝试在 Javafx 中调整画布的大小。我正在使用场景生成器和 fxml。到目前为止,当用户单击画布时,画布变黑,当我调整屏幕大小并单击画布时,只有画布的原始大小变黑(画布没有调整大小)。我不知道如何解决这个问题。任何想法或解决方案都会有很大帮助。

代码:

控制器:

public class MainFXMLController implements Initializable
{

    @FXML
    private Canvas mainCanvas;

    @FXML

    public GraphicsContext gc;

    public void initGraphics()
    {
        gc = mainCanvas.getGraphicsContext2D();
    }

    public void drawClicked(MouseEvent me)
    {

        gc.clearRect(0, 0, mainCanvas.getWidth(), mainCanvas.getHeight());
        gc.setFill(Color.BLACK);
        gc.fillRect(0, 0, mainCanvas.getWidth(), mainCanvas.getHeight());
        System.out.println("Current mosue position: " + me.getX() + ":" + me.getY());
    }

    @Override
    public void initialize(URL url, ResourceBundle rb)
    {
        initGraphics();

    }  
}

Fxml:

<AnchorPane id="AnchorPane" prefHeight="600.0" prefWidth="750.0"  xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"  fx:controller="app.MainFXMLController">
 <children>
    <Canvas fx:id="mainCanvas" height="565.0" onMouseClicked="#drawClicked" width="750.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="35.0" />

主 Java 文件:

public class DrawFx extends Application
{

    @Override
    public void start(Stage stage) throws Exception
    {
        Parent root = FXMLLoader.load(getClass().getResource("MainFXML.fxml"));

        Scene scene = new Scene(root);
        stage.setTitle("DrawFx");
        stage.getIcons().add(new Image("/icon/icon.png"));
        stage.setScene(scene);
        stage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args)
    {
        launch(args);
    }

}

【问题讨论】:

    标签: java html canvas javafx javafx-8


    【解决方案1】:

    首先是一些 Javadocs :)

    Canvas 节点由宽度和高度构成,指定了在其中呈现画布绘图命令的图像大小。所有绘图操作都被裁剪到该图像的边界。

    所以每次用户调整窗口大小时,我们都需要改变画布的宽度,然后我们需要重新绘制画布。

    让我们首先在根布局中添加一个fx:id

    <AnchorPane fx:id="anchorPane" prefHeight="600.0" prefWidth="750.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="app.MainFXMLController">
        <children>
            <Canvas fx:id="mainCanvas" height="565.0" onMouseClicked="#drawClicked" width="750.0"   AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="35.0"/>
        </children>
    </AnchorPane>
    

    下一步是向根布局添加一个更改侦听器,它将为画布设置新的高度和宽度,然后重新绘制它。我们可以在控制器的initialize() 内完成。

    public class Controller implements Initializable {
    
        @FXML
        AnchorPane anchorPane;
    
        @FXML
        private Canvas mainCanvas;
    
        @FXML
        public GraphicsContext gc;
    
        public void initGraphics() {
            gc = mainCanvas.getGraphicsContext2D();
        }
    
        public void drawClicked() {
            gc.clearRect(0, 0, mainCanvas.getWidth(), mainCanvas.getHeight());
            gc.setFill(Color.BLACK);
            gc.fillRect(0, 0, mainCanvas.getWidth(), mainCanvas.getHeight());
        }
    
        @Override
        public void initialize(URL url, ResourceBundle rb) {
            initGraphics();
    
            anchorPane.prefWidthProperty().addListener((ov, oldValue, newValue) -> {
                mainCanvas.setWidth(newValue.doubleValue());
                drawClicked();
            });
    
            anchorPane.prefHeightProperty().addListener((ov, oldValue, newValue) -> {
                mainCanvas.setHeight(newValue.doubleValue());
                drawClicked();
            });
        }
    }
    

    我没有为reDraw() 创建新方法,因为您的drawClicked() 没有做任何事情。但是,一旦更有意义,您可以将这两种方法分开。

    最后一件事是将根布局的prefWidthProperty()prefHeightProperty() 分别绑定到场景的宽度和高度。

    public class Main extends Application {
        public static void main(String[] args) {
            launch(args);
        }
        @Override
        public void start(Stage stage) throws IOException {
            AnchorPane root = FXMLLoader.load(getClass().getResource("MainFXML.fxml"));
    
            Scene scene = new Scene(root);
    
            stage.setTitle("DrawFx");
            stage.setScene(scene);
            stage.show();
    
            root.prefWidthProperty().bind(scene.widthProperty());
            root.prefHeightProperty().bind(scene.heightProperty());
        }
    }
    

    【讨论】:

    • 非常感谢它的工作!但是我想知道在调用 redraw() 函数时是否可以将数据保留在画布上?因此,如果它可以保留以前的图纸,而不是将画布填充为黑色
    • 您可以执行与原始画布相同的逻辑,但所涉及的点会缩放到新的大小。
    【解决方案2】:

    如果您想在 fxml 中调整画布的大小,然后可能会重新绘制其内容,那么绝对最小集是这样的:

    test.fxml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.canvas.Canvas?>
    <?import javafx.scene.layout.Pane?>
    <?import javafx.scene.layout.VBox?>
    
    <VBox xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1"
          fx:controller="test.TestController">
      <children>
        <Pane fx:id="pane" VBox.vgrow="ALWAYS">
          <children>
            <Canvas fx:id="canvas" height="${pane.height}" width="${pane.width}"
                    onWidthChange="#redraw" onHeightChange="#redraw" />
          </children>
        </Pane>
      </children>
    </VBox>
    

    TestController.java

    package test;
    
    import javafx.fxml.FXML;
    import javafx.scene.canvas.Canvas;
    import javafx.scene.canvas.GraphicsContext;
    
    public class TestController {
      @FXML
      private Canvas canvas;
    
      @FXML
      private void redraw() {
        double w=canvas.getWidth();
        double h=canvas.getHeight();
        GraphicsContext gc=canvas.getGraphicsContext2D();
        gc.clearRect(0, 0, w, h);
        gc.beginPath();
        gc.rect(10, 10, w-20, h-20);
        gc.stroke();
      }
    }
    


    包装(它不是功能的一部分,只是为了完整性而提供)

    Test.java

    package test;
    
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    public class Test extends Application {
      @Override
      public void start(Stage primaryStage) throws Exception {
        FXMLLoader loader=new FXMLLoader(getClass().getResource("test.fxml"));
        Parent root=loader.load();
        primaryStage.setTitle("Test");
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
      }
    
      public static void main(String[] args) {
        launch(args);
      }
    }
    

    test 包用于允许模块化魔法,

    module-info.java

    module cnvtest {
      requires transitive javafx.graphics;
      requires javafx.fxml;
      opens test to javafx.fxml;
      exports test;
    }
    

    真的没有更多文件了。

    【讨论】:

      猜你喜欢
      • 2014-06-20
      • 1970-01-01
      • 2014-08-23
      • 1970-01-01
      • 2015-07-06
      • 2016-08-07
      • 1970-01-01
      • 1970-01-01
      • 2017-01-11
      相关资源
      最近更新 更多