javafx FXML绘制后画布为空 [英] javafx FXML Canvas empty after drawing
问题描述
我使用Intellij IDEA进行javafx FXML开发。我使用下面的代码来简单地绘制一个矩形。
public class Main extends Application {
@Override
public void start(Stage primaryStage)throws Exception {
Parent root = FXMLLoader.load(getClass .getResource(sample.fxml));
primaryStage.setTitle(Hello World);
primaryStage.setScene(new Scene(root,600,400));
primaryStage.show();
}
public static void main(String [] args){
launch(args);
}
}
Controller.java / p>
public class Controller implements可初始化{
public Mat image;
@FXML public Canvas img = new Canvas(300,300);
public GraphicsContext gc = img.getGraphicsContext2D();
@FXML private void drawCanvas(ActionEvent event){
gc.setFill(Color.AQUA);
gc.fillRect(10,10,100,100);
}
@Override
public void initialize(URL location,ResourceBundle resources){
gc.setFill(Color.BLACK);
System.out.println(color set to black);
gc.fillRect(50,50,100,100);
System.out.println(draw rectangle);
}
}
我使用setFill()和fillRect Button OnAction和初始化方法。但它仍然不绘制矩形。
sample.fxml
< BorderPane maxHeight = - InfinitymaxWidth = - InfinityminHeight = - InfinityminWidth = - InfinityprefHeight =400.0prefWidth =600.0xmlns =http:// javafx.com/javafx/8xmlns:fx =http://javafx.com/fxml/1fx:controller =sample.Controller> < top> < ToolBar prefHeight =40.0prefWidth =200.0BorderPane.alignment =CENTER> < items> < Button mnemonicParsing =falseonAction =#drawingCanvastext =draw/> < / items> < / ToolBar> < / top> < bottom> < AnchorPane prefHeight =41.0prefWidth =600.0BorderPane.alignment =CENTER> < children> < Label fx:id =colayoutX =14.0layoutY =9.0text =co/> < Label fx:id =rgblayoutX =144.0layoutY =13.0text =RGB/> < Label fx:id =zoomlayoutX =245.0layoutY =9.0text =zoom/> < / children> < / AnchorPane> < / bottom> < center> < ScrollPane fx:id =img_paneprefHeight =200.0prefWidth =200.0BorderPane.alignment =CENTER> < content> < Canvas fx:id =imgheight =286.0width =355.0/> < / content> < / ScrollPane> < / center>< / BorderPane>
这个论坛上有几个问题,但我无法通过快速搜索找到它们。
从不 初始化注释为 @FXML
的字段。 @FXML
的整个要点是该字段在加载FXML文件的过程中被初始化。
在类初始化器中,创建一个 Canvas
,然后将 gc
分配给其图形上下文:
@FXML public Canvas img = new Canvas(300,300);
public GraphicsContext gc = img.getGraphicsContext2D();然后,当您加载FXML文件时, FXMLLoader $ c
$ b $ c>创建一个新的 Canvas
,如FXML所述,将新画布分配给字段 img
在场景图中的新画布(然后您在舞台上显示)。但是, gc
仍然是原始 Canvas
的图形上下文,您从不显示它。因此, gc
上的任何图形操作将永远无法实现。
您需要
public class Controller implements可初始化{
@FXML private Canvas img;
private GraphicsContext gc;
@FXML private void drawCanvas(ActionEvent event){
gc.setFill(Color.AQUA);
gc.fillRect(10,10,100,100);
}
@Override
public void initialize(URL location,ResourceBundle resources){
gc = img.getGraphicsContext2D();
gc.setFill(Color.BLACK);
System.out.println(color set to black);
gc.fillRect(50,50,100,100);
System.out.println(draw rectangle);
}
}
I'm using Intellij IDEA for javafx FXML development. I used the following code to simply draw an rectangle. However, it never showed up.
Main.java
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 600, 400));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Controller.java
public class Controller implements Initializable {
public Mat image;
@FXML public Canvas img = new Canvas(300,300);
public GraphicsContext gc = img.getGraphicsContext2D();
@FXML private void drawCanvas(ActionEvent event) {
gc.setFill(Color.AQUA);
gc.fillRect(10,10,100,100);
}
@Override
public void initialize(URL location, ResourceBundle resources) {
gc.setFill(Color.BLACK);
System.out.println("color set to black");
gc.fillRect(50, 50, 100, 100);
System.out.println("draw rectangle");
}
}
I used setFill() and fillRect() both in Button OnAction and initialize methods. But it still doesn't draw the rectangles.
sample.fxml
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<top>
<ToolBar prefHeight="40.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<items>
<Button mnemonicParsing="false" onAction="#drawCanvas" text="draw" />
</items>
</ToolBar>
</top>
<bottom>
<AnchorPane prefHeight="41.0" prefWidth="600.0" BorderPane.alignment="CENTER">
<children>
<Label fx:id="co" layoutX="14.0" layoutY="9.0" text="co" />
<Label fx:id="rgb" layoutX="144.0" layoutY="13.0" text="RGB" />
<Label fx:id="zoom" layoutX="245.0" layoutY="9.0" text="zoom" />
</children>
</AnchorPane>
</bottom>
<center>
<ScrollPane fx:id="img_pane" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<content>
<Canvas fx:id="img" height="286.0" width="355.0" />
</content>
</ScrollPane>
</center>
</BorderPane>
解决方案 There are several questions like this on this forum, but I cannot find them with a quick search.
You should never initialize a field that is annotated @FXML
. The whole point of @FXML
is that the field is initialized during the process of loading the FXML file.
So in your class initializer, you create a Canvas
and then assign gc
to its graphics context:
@FXML public Canvas img = new Canvas(300,300);
public GraphicsContext gc = img.getGraphicsContext2D();
Then, when you load the FXML file, the FXMLLoader
creates a new Canvas
as described by the FXML, assigns that new canvas to the field img
, and places the new canvas in the scene graph (which you then display in the stage). However, gc
is still the graphics context of the original Canvas
, which you never display. So any graphics operations on gc
will never be realized.
You need
public class Controller implements Initializable {
@FXML private Canvas img ;
private GraphicsContext gc ;
@FXML private void drawCanvas(ActionEvent event) {
gc.setFill(Color.AQUA);
gc.fillRect(10,10,100,100);
}
@Override
public void initialize(URL location, ResourceBundle resources) {
gc = img.getGraphicsContext2D();
gc.setFill(Color.BLACK);
System.out.println("color set to black");
gc.fillRect(50, 50, 100, 100);
System.out.println("draw rectangle");
}
}
这篇关于javafx FXML绘制后画布为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!