在附件中,我已经放置了我的项目的图像,实质上我想在画布中绘制不同类型的形状,如线条,圆形,矩形,三角形ecc,当我单击相对按钮时,我是javafx编程的新手,现在我所理解的是,画布只能在GUI的主线程中进行修改,这就是问题所在,因为当我处理按钮事件“SetonAction”时,我需要主画布的参考来绘制线条或循环ecc。我尝试过使用新的线程,但没有成功。如果有人知道一种方法来做到这一点,我真的很满意。感谢建议在这里输入图像描述
对我来说,很难解决这个问题,所以我做了一些简单的代码来理解事情是如何工作的,看看这个:
public class TE1 extends Application {
private Pane root;
private Pane left;
private StackPane right;
private StackPane drawcontainer;
private CustomizedButton btn;
private CustomizedButton btn1;
private Canvas Drawtable;
private SplitPane divisor;
private double x;
private double y;
private double to_x = 0;
private double to_y = 0;
private int line_no = 1;
@Override
public void start(Stage primaryStage) {
root = new StackPane();
Drawtable = new Canvas(400,400);
Drawtable.setWidth(400);
Drawtable.setHeight(400);
GraphicsContext gc = Drawtable.getGraphicsContext2D();
gc.setFill(Color.CADETBLUE);
gc.fillRect(0, 0, 800, 850);
left = new Pane();
left.setMinSize(400,400);
left.setStyle("-fx-background-color:#d7d6d5;");
right= new StackPane();
right.setAlignment(Pos.CENTER);
// right.setStyle("-fx-background-color: #FFFFFF;");
right.setMinSize(400, 400);
divisor = new SplitPane();
//root.addEventFilter(DrawEvent.DRAW_TYPE,new DrawEventHandler());
//root.addEventHandler(DrawEvent.DRAW_TYPE,new DrawEventHandler());
Drawtable.addEventFilter(DrawEvent.DRAW_TYPE,new DrawEventHandler());
// right.getChildren().add(Drawtable);
btn = new CustomizedButton();
btn1= new CustomizedButton();
btn.Set_identity("linea");
btn1.setMinSize(50,50);
btn.setMinSize(50,50);
btn.setMaxSize(50, 50);
btn.setLayoutX(100);
btn.setLayoutY(100);
btn1.setLayoutX(100);
btn1.setLayoutY(180);
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
this.fireEvent();
}
public void fireEvent()
{
Runnable task = ()-> runTask();
Thread background = new Thread(task);
background.setDaemon(true);
background.start();
}
public void runTask()
{
while(btn.isFocused()){
System.out.println("SONO ATTIVO ");
Drawtable.setOnMousePressed((event) ->setFromPos(event));
System.out.println("x vale :"+x+"y vale: "+y);
Drawtable.setOnMouseDragged((event)->
{
right.getChildren().remove(0);
Canvas temp_canvas = new Canvas(400, 400);
GraphicsContext gc = temp_canvas.getGraphicsContext2D();
gc.setFill(Color.BLUEVIOLET);
// setToPos(event);
// drawLine(gc);
right.getChildren().add(0,temp_canvas);
});
Drawtable.setOnMouseReleased((event) -> {
final Canvas new_line = new Canvas(400, 400);
final GraphicsContext gc = new_line.getGraphicsContext2D();
setToPos(event);
drawLine(gc);
//final new stright line
right.getChildren().add(line_no++,new_line);
});
}
}
});
right.getChildren().addAll( new Canvas(), Drawtable);
left.getChildren().add(btn);
left.getChildren().add(btn1);
divisor.getItems().addAll(left,right);
root.getChildren().addAll(divisor);
Scene scene = new Scene(root, 800, 850);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
private void setFromPos(MouseEvent event) {
this.x = event.getX();
this.y = event.getY();
}
private void setToPos(MouseEvent event) {
this.to_x = event.getX();
this.to_y = event.getY();
}
private void drawLine(GraphicsContext gc) {
gc.setFill(Color.RED);
gc.setStroke(Color.BLACK);
gc.setLineWidth(1);
gc.strokeLine(x, y, to_x, to_y);
}
}
谢谢建议
我以某种方式成功地修改了代码,如下所示:
public class TE1 extends Application {
private Pane root;
private Pane left;
private StackPane right;
private StackPane drawcontainer;
private CustomizedButton btn;
private CustomizedButton btn1;
private Canvas Drawtable;
private SplitPane divisor;
private double x;
private double y;
private double to_x = 0;
private double to_y = 0;
private int line_no = 1;
private Thread background;
@Override
public void start(Stage primaryStage) {
root = new StackPane();
Drawtable = new Canvas(400,400);
Drawtable.setWidth(400);
Drawtable.setHeight(400);
GraphicsContext gc = Drawtable.getGraphicsContext2D();
left = new Pane();
left.setMinSize(400,400);
left.setStyle("-fx-background-color:#d7d6d5;");
right= new StackPane();
right.setAlignment(Pos.CENTER);
right.setStyle("-fx-background-color: #FFFFFF;");
right.setMinSize(400, 400);
divisor = new SplitPane();
btn = new CustomizedButton();
btn1= new CustomizedButton();
btn.Set_identity("linea");
btn1.setMinSize(50,50);
btn.setMinSize(50,50);
btn.setMaxSize(50, 50);
btn.setLayoutX(100);
btn.setLayoutY(100);
btn1.setLayoutX(100);
btn1.setLayoutY(180);
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
this.fireEvent();
}
public void fireEvent()
{
Runnable task = ()-> runTask();
Thread background = new Thread(task);
background.setDaemon(true);
background.start();
}
public void runTask()
{
while(btn.isFocused()){
System.out.println("SONO ATTIVO ");
Drawtable.setOnMousePressed((event) ->setFromPos(event));
System.out.println("x vale :"+x+"y vale: "+y);
Drawtable.setOnMouseDragged((event)->
{
right.getChildren().remove(0);
Canvas temp_canvas = new Canvas(400, 400);
GraphicsContext gc = temp_canvas.getGraphicsContext2D();
setToPos(event);
drawLine(gc);
right.getChildren().add(0,temp_canvas);
});
Drawtable.setOnMouseReleased((event) -> {
final Canvas new_line = new Canvas(400, 400);
final GraphicsContext gc = new_line.getGraphicsContext2D();
setToPos(event);
drawLine(gc);
//final new stright line
right.getChildren().add(line_no++,new_line);
});
}
System.out.println("Focused btn state :"+btn.isFocused());
background.interrupt();
}
});
right.getChildren().addAll( new Canvas(), Drawtable);
left.getChildren().add(btn);
left.getChildren().add(btn1);
divisor.getItems().addAll(left,right);
root.getChildren().addAll(divisor);
Scene scene = new Scene(root, 800, 850);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
private void setFromPos(MouseEvent event) {
this.x = event.getX();
this.y = event.getY();
}
private void setToPos(MouseEvent event) {
this.to_x = event.getX();
this.to_y = event.getY();
}
private void drawLine(GraphicsContext gc) {
gc.setFill(Color.RED);
gc.setStroke(Color.BLACK);
gc.setLineWidth(1);
gc.strokeLine(x, y, to_x, to_y);
}
}
但现在我不明白为什么当按钮没有聚焦时,它不会停止在画布上画线。有什么建议吗??
这里没有必要使用多线程,也不是一个好主意。
注册事件处理程序不是一个长时间运行的操作,反复使用相同的逻辑重新分配匿名类不会改变任何事情。此外,这些修改需要从JavaFX应用程序线程进行。
另一个应该提到的问题是,在鼠标手势期间,您正在重新创建<code>画布</code>。您应该避免这样做,而是重用现有的画布
。还应避免每行堆叠一个画布
。如果您需要一个用于当前绘制的线和一个用于完成的线的画布,则为2<code>画布</code>es。顺便说一句,使用行
s将更容易实现。
我也推荐< code>ToggleButton来完成这种任务。这允许你访问一个独立于焦点的状态。您应该侦听属性,而不是重复查询状态(无论您是使用< code>selected还是< code>focused来添加/移除侦听器):
private Pane root;
private Pane left;
private StackPane right;
private Button btn1;
private Canvas Drawtable;
private Canvas drawingCanvas;
private GraphicsContext drawingContext;
private SplitPane divisor;
@Override
public void start(Stage primaryStage) {
root = new StackPane();
Drawtable = new Canvas(400, 400);
Drawtable.setWidth(400);
Drawtable.setHeight(400);
// second Canvas for drawing stacked on top of the other canvas
drawingCanvas = new Canvas(Drawtable.getWidth(), Drawtable.getHeight());
drawingContext = drawingCanvas.getGraphicsContext2D();
left = new Pane();
left.setMinSize(400, 400);
left.setStyle("-fx-background-color:#d7d6d5;");
right = new StackPane(Drawtable, drawingCanvas);
right.setAlignment(Pos.CENTER);
right.setStyle("-fx-background-color: #FFFFFF;");
right.setMinSize(400, 400);
divisor = new SplitPane();
ToggleButton btn = new ToggleButton();
btn1 = new Button();
btn.setText("linea");
btn1.setMinSize(50, 50);
btn.setMinSize(50, 50);
btn.setMaxSize(50, 50);
btn.setLayoutX(100);
btn.setLayoutY(100);
btn1.setLayoutX(100);
btn1.setLayoutY(180);
btn.selectedProperty().addListener(new ChangeListener<Boolean>() {
private double x;
private double y;
private void drawLine(GraphicsContext gc, double endX, double endY) {
gc.setStroke(Color.BLACK);
gc.setLineWidth(1);
gc.strokeLine(x, y, endX, endY);
}
private final EventHandler<MouseEvent> pressedHandler = (event) -> {
x = event.getX();
y = event.getY();
};
private final EventHandler<MouseEvent> draggedHandler = (event) -> {
// remove old content & draw new content
drawingContext.clearRect(0, 0, drawingCanvas.getWidth(), drawingCanvas.getHeight());
drawLine(drawingContext, event.getX(), event.getY());
};
private final EventHandler<MouseEvent> releasedHandler = (event) -> {
// clear canvas for line drawing
drawingContext.clearRect(0, 0, drawingCanvas.getWidth(), drawingCanvas.getHeight());
// draw line on background canvas
final GraphicsContext gc = Drawtable.getGraphicsContext2D();
drawLine(gc, event.getX(), event.getY());
};
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
// add/remove event handlers based on toggle state of the button
if (newValue) {
drawingCanvas.addEventHandler(MouseEvent.MOUSE_PRESSED, pressedHandler);
drawingCanvas.addEventHandler(MouseEvent.MOUSE_DRAGGED, draggedHandler);
drawingCanvas.addEventHandler(MouseEvent.MOUSE_RELEASED, releasedHandler);
} else {
drawingCanvas.removeEventHandler(MouseEvent.MOUSE_PRESSED, pressedHandler);
drawingCanvas.removeEventHandler(MouseEvent.MOUSE_DRAGGED, draggedHandler);
drawingCanvas.removeEventHandler(MouseEvent.MOUSE_RELEASED, releasedHandler);
}
}
});
left.getChildren().add(btn);
left.getChildren().add(btn1);
divisor.getItems().addAll(left, right);
root.getChildren().addAll(divisor);
Scene scene = new Scene(root, 800, 850);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
有没有可能通过它们的方程式在画布中画出曲线呢?如果是,怎么做?假设我有一个数学方程y=0,5*x^2,如何打印方程的图形? 我尝试使用和方法,但未成功。
我是Android新手,发现了很多东西。但现在我很沮丧。我想做一个六角形棋盘游戏,用瓷砖。我找到了很多芭蕾舞团,最后决定画出我想要的六边形。 我创建了一个从视图扩展的“Hex”类,添加了一些变量等等。以下是我在主XML布局中的内容: r=大小,x和y是画布上的偏移。以下是我在活动中看到的内容:主活动屏幕 但现在我想选择单十六进制。例如,我想选择左上角的,或右下角的。我在每个视图上都添加了OnCli
我编写了这段代码,可以在JavaFX画布上绘制。它可以很好地工作,但我不知道如何重新绘制画布(比如在Swing中),以便在新画布上重新开始绘制。这是我的代码,非常感谢你的帮助!马里奥
实际上,我可以使用函数来完成。我从“HTML5画布-如何在图像背景上画一条线?”中得到的东西。但是我需要在不使用from函数的情况下绘制图像,如下所示:
我有以下代码应该在图像中绘制线条。我的代码是: 如果我编写,它实际上可以工作。但是我的数组很长并且来自一个输入。