Im trying to clear simple canvas in JavaFX.
Start function
Canvas canvas = new Canvas();
Group root = new Group(canvas);
Scene scene = new Scene(root, 1400, 1000);
If user want to load game, then loadSave boolean variable sets to 'true'
if(loadSave){
//Clear scene and load new with circles from file
}
Else, it loads new game
else if(!loadSave){
drawSquares(scene, root);
}
I'll really appreciate your help.
I have special group for my Scene - root.
I can delete only this group using
root.getChildren().clear();
This feature has many uses, I can now eg add items that I want to remove into this group.
To remove only e.g Circles from group(where my Canvas is) I used
void clearScene(Group root) {
for (Circle circle : circles) {
root.getChildren().remove(circle);
}
circles.clear();
}
Related
I build a simple JavaFX App and I wan't to create a circle in the center of an ellipse when the Mouse enters the ellipse.
This is some of the Code:
ellipse = new Ellipse(30,30,40,40);
ellipse.setFill(Color.TRANSPARENT);
ellipse.setStroke(Color.BLACK);
ellipse.setOnMouseEntered(event -> {
Circle circle = new Circle();
circle.setCenterX(30);
circle.setCenterY(30);
circle.setFill(Color.GREEN);
group.getChildren().add(circle);
group.getChildren().removeAll(ellipse);
System.out.println("Added Circle");
});
group = new Group();
group.getChildren().add(ellipse);
vBox = new VBox();
vBox.getChildren().add(group);
The Vbox is added to a Scene and the Scene is added to the PrimaryStage.
If I run the program and my Mouse enters the ellipse the ellipse will be removed but the circle will not be added.
Can anyone explain me why?
First of all this seems to be the wrong way of implementing an dynamic node Adding / removing thing. What would be the right way?
But I'm also interested in why can I remove a Node so easy but I can't added it so easy?
My mistake, the Circle has no radius...
If I add a radius to the circle everything works fine,
Using JavaFX I have created a simple rectangle object, and I want to be able to put a text object inside that rectangle, and for it to automatically stay aligned within the rectangle. The code I have to draw the rectangle is:
public static Scene createScene() {
Group root = new Group();
Scene scene = new Scene(root, Color.ALICEBLUE);
Rectangle rectangle_red = new Rectangle();
rectangle_red.setFill(Color.TRANSPARENT);
rectangle_red.setStroke(Color.BLACK);
rectangle_red.setX(50);
rectangle_red.setY(50);
rectangle_red.setWidth(200);
rectangle_red.setHeight(100);
rectangle_red.setCursor(Cursor.HAND);
rectangle_red.setOnMousePressed(circleOnMousePressedEventHandler);
rectangle_red.setOnMouseDragged(circleOnMouseDraggedEventHandler);
root.getChildren().add(rectangle_red);
return scene;
}
The Handlers I have attached to the rectangle allow me to drag the rectangles anywhere in the window. How do I place text inside the rectangle such that it stays aligned as I drag the shape around the screen?
As illustrated in the last example seen here, the Animation Basics example TimelineEvents does this by adding a Circle and some Text to a StackPane, which centers its children by default. The stack can then be moved within an enclosing Group as a unit.
final Circle circle = new Circle(…);
final Text text = new Text (…);
final StackPane stack = new StackPane();
stack.getChildren().addAll(circle, text);
…
stack.setLayoutX(30);
stack.setLayoutY(30);
I am making a sliding animation to switch a scene to another scene, but when I call this method, it has a delay for switching scene. I found that the cause is a method snapshot() of class Scene.
Does anyone have a solution?
code:
public void switchScene(Scene target) {
Scene current = getPrimaryStage().getScene();
WritableImage beforeImage;
WritableImage afterImage;
int width = ((int) ((Region) current.getRoot()).getWidth());
int height = ((int) ((Region) current.getRoot()).getHeight());
beforeImage = new WritableImage(width, height);
ImageView leftImage = new ImageView(current.snapshot(beforeImage));
afterImage = new WritableImage(width, height);
ImageView rightImage = new ImageView(target.snapshot(afterImage));
leftImage.setTranslateX(0);
rightImage.setTranslateX(width);
StackPane animation = new StackPane(leftImage, rightImage);
animation.setPrefSize(target.getWidth(), target.getHeight());
primaryStage.setScene(new Scene(animation));
Timeline timeline = new Timeline();
KeyValue kv = new KeyValue(rightImage.translateXProperty(), 0, Interpolator.EASE_BOTH);
KeyFrame kf = new KeyFrame(Duration.seconds(0.75), kv);
timeline.getKeyFrames().add(kf);
timeline.setOnFinished(t -> {
// remove pane and restore scene 1
primaryStage.setScene(target);
});
timeline.play();
}
Taking a snapshot in this way is an inherently slow operation, there's not a great deal that can be done to speed it up while staying in Java land. As suggested in the comment, if you really want to take a snapshot then a better approach would be to use the asynchronous method, which won't block the UI thread while it runs (so while they'll still be a delay, your app will still remain responsive.)
However, if I've understood your example correctly, there's absolutely no need to use screenshots at all - why are you using images rather than just animating the nodes themselves? Remember that all JavaFX elements are nodes of the scenegraph, so can be animated in the same way. So instead of:
StackPane animation = new StackPane(leftImage, rightImage);
You should just be able to do:
StackPane animation = new StackPane(source, target);
...then use this to animate the panes directly without going through the slow process of taking screenshots.
This is kind of a vague question, but I'm trying to create a code editor using JavaFX Canvas technologies and its being incredibly slow for what I'd like.
Take the following code for example
public class JavaFXApplication13 extends Application {
#Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
int extent = 6300;
System.out.println(System.getProperty("java.version"));
Canvas cvs = new Canvas(extent,extent);
ScrollPane scpn = new ScrollPane();
root.setTop(cvs);
scpn.setContent(root);
root.autosize();
scpn.autosize();
GraphicsContext ctx = cvs.getGraphicsContext2D();
for(int i = 0; extent / 300 > i; i++){
ctx.setFill(Color.RED);
ctx.fillRect(i*300, 0, 100, extent);
ctx.setFill(Color.BLUE);
ctx.fillRect(i*300+100, 0, 100, extent);
ctx.setFill(Color.GREEN);
ctx.fillRect(i*300+200, 0, 100, extent);
}
//// root.getChildren().add(btn);
Scene scene = new Scene(scpn, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
If you try to slide pane around, theres a good few seconds between when you move the cursor and when the scrollbar and the scroll pane update. This has to do with the size of the canvas, which is set to 6300, which is nothing. I can open NotePad and get line heights in the million and its able to draw them with ease.
Performance is even worse when trying to draw on a large sized canvas, simple
onKeyPress((a) -> drawText(a.getText(), ...));
takes seconds to process.
I guess what I'm trying to say is, is this performance normal? or should I just suck it up and move on to something more powerful such as OpenGL?
A code editor should be virtual and only draw the lines you see on screen! So IMHO your use of canvas is completely incorrect!
Canvas at its heart can be seen like a buffered image you can draw on and on the OpenGL / Directx side only sees a image.
Why reinvent the wheel there are at least 2 opensource javafx code editors. See https://tomasmikula.github.io/blog/ and http://tomsondev.bestsolution.at/2014/08/11/efxclipse-1-0-new-features-styledtext-control-to-build-a-code-editor-framework/
I tested JavaFX for a game project about 6 months ago, I was drawing 10000 rectangles and using an animation timer to change the color of each rectangle 60 times a second.
I found that using the canvas for this was really slow and was getting about a frame a second. I changed to just using the scene graph by just adding JavaFX rectangle nodes to a Group node and it worked with no lag.
I was surprised that using JavaFX objects was way more efficient that using the canvas, I am now working on my second JavaFX 2 game using nodes in the scene graph.
Coding a GUI in a Java project I've encountered a problem with JavaFX.
I've not found any soulutions for my specific problem, so here I am:)
Is it possible to let a JavaFX scene be resizeable by the user and at the same time have it not resized by child nodes, that are bigger, than the window?
Here is some sample code:
#Override
public void startGUI(int width, int height) {
this.main = new MainWindow(this, this.logic);
this.scene = new Scene(this.main.getRoot());
this.main.setScene(this.scene);
this.primaryStage.setScene(this.scene);
this.primaryStage.setMinHeight(height);
this.primaryStage.setMinWidth(width);
}
The 'MainWindow' has got a childnode, that can be very big (>1024x768).
I want the window not to be resized by this node, but at the same time, the user should be able to resize the window by dragging its borders.
Use a Scene constructor which specifies initial size constraints.
For example:
Scene scene = new Scene(root, 600, 400);
That way the initial size of the Scene will be taken from these constraints rather than calculated from the preferred size of the root node.