JavaFX 从 canvas 中删除最后绘制的对象
JavaFX deleting last drawn object from canvas
简介:
我创建了一个 canvas,我的 objective 正在您点击 canvas 的地方创建圆圈。但我也希望能够删除我绘制的圆圈或至少是最后绘制的圆圈。在圆圈与背景颜色相同的地方重新绘制不是一个好的解决方案。因为如果圆圈下还有其他东西,它们也会被删除。例如,在此应用程序中,2 个圆圈可能有交点,当您尝试删除第二个圆圈时,这些交点将为空,这意味着也将删除第一个圆圈的某些部分。所以我想到了创建 2nd canvas。每次我在绘制圆圈之前单击 canvas 上的某处时,我都会将主要 canvas 分配给备份 canvas。当我想删除最后绘制的对象时,我可以加载备份 canvas.
现在,我尝试按照上面的说明进行操作,但无法按我的预期进行。事实上,我什至在其他事物上看到了一些奇怪的(至少对我而言)行为。
我所做的基本上是创建 2 个相同大小的 canvas。
public class Main extends Application {
double ldx, ldy, diameter;
Canvas lastCanvas = new Canvas(800,600);
Canvas pane1 = new Canvas(800,600);
@Override
public void start(Stage primaryStage) throws Exception{
System.out.println("Hello");
HBox root = new HBox();
GraphicsContext gc = pane1.getGraphicsContext2D();
pane1.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
// Draw circle around x,y
lastCanvas = pane1;
diameter = 25.0;
ldx = event.getSceneX() - ( diameter/2 );
ldy = event.getSceneY() - ( diameter/2 );
gc.strokeOval(ldx, ldy, diameter, diameter);
System.out.println("Clicked");
}
});
VBox pane2 = new VBox(10);
pane2.setPrefSize(224,600);
Button button1 = new Button("Clear Last Drawn");
button1.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
pane1 = lastCanvas;
System.out.println("Last canvas loaded");
}
});
pane2.getChildren().addAll(button1);
pane1.setStyle("-fx-background-color: #224488");
pane2.setStyle("-fx-background-color: #224488");
root.getChildren().addAll(pane1, pane2);
Scene scene1 = new Scene(root, 1024, 600);
primaryStage.setScene(scene1);
primaryStage.setTitle("Mouse Clicker");
primaryStage.show();
}
}
预期的行为是,每次我单击按钮时,它都会在我绘制最后一个对象之前加载 lastCanvas,即 canvas。但事实并非如此。我在 button1 的鼠标事件
中尝试了类似的东西
root.getChildren().removeAll();
root.getChildren().addAll(lastCanvas, pane2);
每次单击按钮时都会在控制台上生成错误。另一个问题是我试图创建第二个场景。
HBox root2 = new HBox();
root2.getChildren().addAll(lastCanvas, pane2);
虽然我没有在任何地方使用 root2,但这样做会令人惊讶地删除 pane2 上的所有内容。我在这里所做的就是创建一个新的 HBox 并将 pane2 添加到该 hbox 中。为什么这样做会从我的 primaryStage 中删除 pane2 而不是留下白色 space?
此外,如果您有其他建议删除在 canvas 上绘制的最后一个对象 - 一次或直到 canvas 完全为空 - 你也可以告诉我,而不是试图解决我上面的代码做错了。
没有分析问题,我以你的代码为基础提出以下解决方案
private final double diameter = 25;
private final LinkedList<Point2D> centers = new LinkedList<>();
private final Canvas pane1 = new Canvas(800, 600);
@Override
public void start(Stage primaryStage) throws Exception
{
System.out.println("Hello");
HBox root = new HBox();
pane1.setOnMouseClicked((MouseEvent event) ->
{
centers.add(new Point2D(event.getSceneX(), event.getSceneY()));
render();
System.out.println("Clicked");
});
VBox pane2 = new VBox(10);
pane2.setPrefSize(224, 600);
Button button1 = new Button("Clear Last Drawn");
button1.setOnMouseClicked((MouseEvent event) ->
{
if (!centers.isEmpty())
{
centers.removeLast();
render();
System.out.println("Last canvas loaded");
}
});
pane2.getChildren().addAll(button1);
pane1.setStyle("-fx-background-color: #224488");
pane2.setStyle("-fx-background-color: #224488");
root.getChildren().addAll(pane1, pane2);
Scene scene1 = new Scene(root, 1024, 600);
primaryStage.setScene(scene1);
primaryStage.setTitle("Mouse Clicker Project (Berk YATKIN)");
primaryStage.show();
}
private void render()
{
pane1.getGraphicsContext2D().clearRect(0, 0, pane1.getWidth(), pane1.getHeight());
centers.forEach((p) ->
{
pane1.getGraphicsContext2D().strokeOval(
p.getX() - (diameter / 2),
p.getY() - (diameter / 2),
diameter,
diameter);
});
}
同样不分析问题我就先问问你为什么非要用一个canvas。场景图更适合这类问题。您可以向其中添加(几乎)任意数量的圆圈,并以您喜欢的任何顺序删除任意数量的圆圈。还有什么比这更容易的呢?
你要的,所以在这儿:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
BorderPane root = new BorderPane();
Pane graphicsPane = new Pane();
root.setCenter(graphicsPane);
graphicsPane.setOnMouseClicked(e -> {
// Draw circle around x,y
Circle circle = new Circle(e.getX(), e.getY(), 50.0);
circle.setStroke(Color.RED);
circle.setStrokeWidth(4.0);
circle.setFill(null);
graphicsPane.getChildren().add(circle);
});
VBox pane2 = new VBox(10);
pane2.setPrefWidth(224);
Button button1 = new Button("Clear Last Drawn");
button1.setOnAction(e -> {
int numCircles = graphicsPane.getChildren().size();
if (numCircles > 0) {
graphicsPane.getChildren().remove(numCircles - 1);
}
});
pane2.getChildren().addAll(button1);
root.setRight(pane2);
graphicsPane.setStyle("-fx-background-color: #aaaaaa");
pane2.setStyle("-fx-background-color: #224488");
Scene scene1 = new Scene(root, 1024, 600);
primaryStage.setScene(scene1);
primaryStage.setTitle("Mouse Clicker");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
这是直接使用场景图的解决方案。这个例子也可以很容易地扩展,通过图形选择来移动圆圈或删除圆圈。使用 canvas.
不容易实现的所有事情
简介:
我创建了一个 canvas,我的 objective 正在您点击 canvas 的地方创建圆圈。但我也希望能够删除我绘制的圆圈或至少是最后绘制的圆圈。在圆圈与背景颜色相同的地方重新绘制不是一个好的解决方案。因为如果圆圈下还有其他东西,它们也会被删除。例如,在此应用程序中,2 个圆圈可能有交点,当您尝试删除第二个圆圈时,这些交点将为空,这意味着也将删除第一个圆圈的某些部分。所以我想到了创建 2nd canvas。每次我在绘制圆圈之前单击 canvas 上的某处时,我都会将主要 canvas 分配给备份 canvas。当我想删除最后绘制的对象时,我可以加载备份 canvas.
现在,我尝试按照上面的说明进行操作,但无法按我的预期进行。事实上,我什至在其他事物上看到了一些奇怪的(至少对我而言)行为。
我所做的基本上是创建 2 个相同大小的 canvas。
public class Main extends Application {
double ldx, ldy, diameter;
Canvas lastCanvas = new Canvas(800,600);
Canvas pane1 = new Canvas(800,600);
@Override
public void start(Stage primaryStage) throws Exception{
System.out.println("Hello");
HBox root = new HBox();
GraphicsContext gc = pane1.getGraphicsContext2D();
pane1.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
// Draw circle around x,y
lastCanvas = pane1;
diameter = 25.0;
ldx = event.getSceneX() - ( diameter/2 );
ldy = event.getSceneY() - ( diameter/2 );
gc.strokeOval(ldx, ldy, diameter, diameter);
System.out.println("Clicked");
}
});
VBox pane2 = new VBox(10);
pane2.setPrefSize(224,600);
Button button1 = new Button("Clear Last Drawn");
button1.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
pane1 = lastCanvas;
System.out.println("Last canvas loaded");
}
});
pane2.getChildren().addAll(button1);
pane1.setStyle("-fx-background-color: #224488");
pane2.setStyle("-fx-background-color: #224488");
root.getChildren().addAll(pane1, pane2);
Scene scene1 = new Scene(root, 1024, 600);
primaryStage.setScene(scene1);
primaryStage.setTitle("Mouse Clicker");
primaryStage.show();
}
}
预期的行为是,每次我单击按钮时,它都会在我绘制最后一个对象之前加载 lastCanvas,即 canvas。但事实并非如此。我在 button1 的鼠标事件
中尝试了类似的东西root.getChildren().removeAll();
root.getChildren().addAll(lastCanvas, pane2);
每次单击按钮时都会在控制台上生成错误。另一个问题是我试图创建第二个场景。
HBox root2 = new HBox();
root2.getChildren().addAll(lastCanvas, pane2);
虽然我没有在任何地方使用 root2,但这样做会令人惊讶地删除 pane2 上的所有内容。我在这里所做的就是创建一个新的 HBox 并将 pane2 添加到该 hbox 中。为什么这样做会从我的 primaryStage 中删除 pane2 而不是留下白色 space?
此外,如果您有其他建议删除在 canvas 上绘制的最后一个对象 - 一次或直到 canvas 完全为空 - 你也可以告诉我,而不是试图解决我上面的代码做错了。
没有分析问题,我以你的代码为基础提出以下解决方案
private final double diameter = 25;
private final LinkedList<Point2D> centers = new LinkedList<>();
private final Canvas pane1 = new Canvas(800, 600);
@Override
public void start(Stage primaryStage) throws Exception
{
System.out.println("Hello");
HBox root = new HBox();
pane1.setOnMouseClicked((MouseEvent event) ->
{
centers.add(new Point2D(event.getSceneX(), event.getSceneY()));
render();
System.out.println("Clicked");
});
VBox pane2 = new VBox(10);
pane2.setPrefSize(224, 600);
Button button1 = new Button("Clear Last Drawn");
button1.setOnMouseClicked((MouseEvent event) ->
{
if (!centers.isEmpty())
{
centers.removeLast();
render();
System.out.println("Last canvas loaded");
}
});
pane2.getChildren().addAll(button1);
pane1.setStyle("-fx-background-color: #224488");
pane2.setStyle("-fx-background-color: #224488");
root.getChildren().addAll(pane1, pane2);
Scene scene1 = new Scene(root, 1024, 600);
primaryStage.setScene(scene1);
primaryStage.setTitle("Mouse Clicker Project (Berk YATKIN)");
primaryStage.show();
}
private void render()
{
pane1.getGraphicsContext2D().clearRect(0, 0, pane1.getWidth(), pane1.getHeight());
centers.forEach((p) ->
{
pane1.getGraphicsContext2D().strokeOval(
p.getX() - (diameter / 2),
p.getY() - (diameter / 2),
diameter,
diameter);
});
}
同样不分析问题我就先问问你为什么非要用一个canvas。场景图更适合这类问题。您可以向其中添加(几乎)任意数量的圆圈,并以您喜欢的任何顺序删除任意数量的圆圈。还有什么比这更容易的呢?
你要的,所以在这儿:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
BorderPane root = new BorderPane();
Pane graphicsPane = new Pane();
root.setCenter(graphicsPane);
graphicsPane.setOnMouseClicked(e -> {
// Draw circle around x,y
Circle circle = new Circle(e.getX(), e.getY(), 50.0);
circle.setStroke(Color.RED);
circle.setStrokeWidth(4.0);
circle.setFill(null);
graphicsPane.getChildren().add(circle);
});
VBox pane2 = new VBox(10);
pane2.setPrefWidth(224);
Button button1 = new Button("Clear Last Drawn");
button1.setOnAction(e -> {
int numCircles = graphicsPane.getChildren().size();
if (numCircles > 0) {
graphicsPane.getChildren().remove(numCircles - 1);
}
});
pane2.getChildren().addAll(button1);
root.setRight(pane2);
graphicsPane.setStyle("-fx-background-color: #aaaaaa");
pane2.setStyle("-fx-background-color: #224488");
Scene scene1 = new Scene(root, 1024, 600);
primaryStage.setScene(scene1);
primaryStage.setTitle("Mouse Clicker");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
这是直接使用场景图的解决方案。这个例子也可以很容易地扩展,通过图形选择来移动圆圈或删除圆圈。使用 canvas.
不容易实现的所有事情