[英]JavaFX resize canvas in fxml
我正在尝试在 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();
}
}
文件格式:
<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);
}
}
首先是一些 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());
}
}
如果你想在 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; }
并且真的没有更多文件了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.