setTranslate() doesn't work in nested panes in JavaFX - javafx

I am working on a GUI, where I need to move objects in exact part of GUI. Main windows is split into few parts and I want to be able to move objects in one of these parts.
I tried to write simple code, where I just move simple rectangle in root Group, to understand how transition translation works. Everything went well. When I wanted to do the exact same thing in my GUI (in one of nested Group), it didn't work.
It shows, that new translations were set to object, but object didn't move at all.
I did the exact same thing, except Groupt isn't root.
Code:
/* imports, main() */
public void start(Stage primaryStage) throws Exception {
Button tmpButton = new Button("Just fill the space");
Rectangle rect = new Rectangle(0, 0, 20, 20);
rect.setOnMousePressed(mousePressedEvent);
rect.setOnMouseDragged(mouseDraggedEvent);
Group movablePlace = new Group();
movablePlace.getChildren().add(rect);
VBox root = new Root();
root.geChildren().addAll(tmpButton, movablePlace);
primaryStage.setScene(new Scene(root, 500, 400));
primaryStage.show();
}
EventHandler<MouseEvent> mousePressedEvent = new EventHandler<MouseEvent>() {
/* getting coordinates works fine */
};
EventHandler<MouseEvent> mouseDraggedEvent = new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
/* actualize new coordinates and offset - works fine */
((Rectangle)event.getSource).setTranslateX(newTranslationX);
((Rectangle)event.getSource).setTranslateY(newTranslationY);
/* translations of rectangle are set correctly, but it doesn't move */
}
};
Can someone clear up to me, what I did wrong or misunderstood?
Thank you!

Related

JavaFX keyboard input stops working after adding buttons

I am building a game engine as a school project. When I add button to the same group as where I have my canvas, I can't control my player anymore with keyboard. Buttons and everything else still works like normal.
My code is pretty huge, so this is a simplified code of the problem:
public abstract class GEngine extends Application {
public void start(Stage theStage) throws Exception {
try {
this.stage = theStage;
Group root = new Group();
Scene theScene = new Scene(root);
stage.setScene(theScene);
Canvas canvas = new Canvas(windowWidth, windowHeight);
root.getChildren().add(canvas);
Button btn = new Button("new");
btn.setOnMousePressed(e->System.out.println("press"));
root.getChildren().add(btn);
Timeline gameLoop = new Timeline();
gameLoop.setCycleCount(Timeline.INDEFINITE);
// Handle input
theScene.setOnKeyPressed(Input::handlePressed);
theScene.setOnKeyReleased(Input::handleReleased);
// Control game loop and it's speed
KeyFrame kf = new KeyFrame(
Duration.seconds(0.017), // 60 FPS
(e)->this.controlGameLoop());
gameLoop.getKeyFrames().add( kf );
gameLoop.play();
stage.show();
} catch (Exception e) {
e.printStackTrace();
stop();
}
}
}
There is probably something happening on the background which I just don't understand. I can show my Input class code too if somebody wants to see it, but in my understanding it's not necessary.
I have tried using AnchorPane as main root and make a separate groups for buttons and canvas which I add the to the AnchorPane, but that did not help at all. That was pretty much the only offered solution I could find from google.
Adding btn.setFocusTraversable(false); fixed the problem, thanks to Luxusproblem for providing the answer!

JavaFX Button invisble, but can be pressed issue

EDIT:
I've determined that the following line is the cause:
primaryStage.initStyle(StageStyle.UNIFIED);
Can any explain why it would be causing this issue?
JDK: 13.0.1
FX: 13
Eclipse: 2019-09 R (4.13.0)
Maybe I'm going crazy, because I feel like I do pretty good with JavaFX... But for some reason, the buttons don't appear, but I can press them, and my logger says the buttons are pressed. I can press the exit button (although invisible), and it quits as expected... so why are the button invisible?
I've attempted to set visibility to true, but that did nothing too. The button sizes appear to be set properly too.
public class test extends Application {
private Button gameButton = new Button("Game");
private Button mapEditorButton = new Button("Map Editor");
private Button exitButton = new Button("Exit");
private static final int buttonHeight = 25;
private static final int buttonWidth = 100;
private static final int screenwidth = 350;
private static final int screenHeight = 150;
private Scene theScene;
private Stage primaryStage;
private VBox root = new VBox(30);
private HBox top = new HBox(10);
public void start(Stage stage) {
primaryStage = stage;
setButtonSizes();
root.setPrefSize(screenwidth, screenHeight);
root.resize(screenwidth, screenHeight);
root.setAlignment(Pos.CENTER);
root.getChildren().addAll(top, exitButton);
top.getChildren().addAll(gameButton, mapEditorButton);
top.setAlignment(Pos.CENTER);
theScene = new Scene(root);
primaryStage.setTitle("Menu Selector");
primaryStage.setWidth(screenwidth);
primaryStage.setHeight(screenHeight);
primaryStage.setResizable(false);
primaryStage.initStyle(StageStyle.UNIFIED);
primaryStage.setScene(theScene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
private void setButtonSizes() {
gameButton.setMinSize(buttonWidth, buttonHeight);
gameButton.setMaxSize(buttonWidth, buttonHeight);
gameButton.setPrefSize(buttonWidth, buttonHeight);
mapEditorButton.setMinSize(buttonWidth, buttonHeight);
mapEditorButton.setMaxSize(buttonWidth, buttonHeight);
mapEditorButton.setPrefSize(buttonWidth, buttonHeight);
exitButton.setMinSize(buttonWidth, buttonHeight);
exitButton.setMaxSize(buttonWidth, buttonHeight);
exitButton.setPrefSize(buttonWidth, buttonHeight);
}
}
Here's an image of the problem:
After commenting out lines of your code to try to discover what was causing the behavior, I found that it was this line...
primaryStage.initStyle(StageStyle.UNIFIED);
Then I looked at the javadoc for class StageStyle. It states...
Specifies the style for this stage. This must be done prior to making the stage visible. The style is one of: StageStyle.DECORATED, StageStyle.UNDECORATED, StageStyle.TRANSPARENT, or StageStyle.UTILITY
Hmm, UNIFIED isn't mentioned there. Nonetheless, your code compiles and runs without error, so UNIFIED must be a valid value. So then I looked at the javadoc for UNIFIED and read this...
This is a conditional feature, to check if it is supported see javafx.application.Platform.isSupported
So running this method...
Platform.isSupported(ConditionalFeature.UNIFIED_WINDOW)
returned true on my Windows 10 64-bit machine running [Oracle] JDK 13.0.1
Despite this, using StageStyle.UNIFIED causes a problem. My guess is it may be a bug. In any case, if you remove this line (or comment it out), you will see your buttons.

Bi-coloring JavaFX TableCell Background?

I have a javafx.scene.control.TableView containing some javafx.scene.control.TableColumns containing some javafx.scene.control.TextFields. Some of the TextFields should get a bi-coloured background: diagonally divided, the upper left half one colour, the lower right half another colour. Like the cells for Ge, Sb, Po in https://de.wikipedia.org/wiki/Periodensystem#/media/Datei:Periodensystem_deutsch_-_neue_Farben.svg. Is this possible without a background image?
Edit: added some code. For simplicity’s sake, i omitted the surrounding table and use now a javafx.scene.text.Text instead of a javafx.scene.control.TextField. The basic setup that follows gives a uniform background to the StackPane which is a start.
public class DividedBackgroundDemo extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Test: Diagonally divided colour background");
Text txt = new Text("Text");
txt.setFont(Font.font("Arial", FontWeight.BOLD, FontPosture.REGULAR, 50));
StackPane root = new StackPane();
root.getChildren().add(txt);
root.setStyle("-fx-background-color: blue;");
primaryStage.setScene(new Scene(root, 200, 200));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Later on, when i will use a 13x13 grid of Text, i will have to imbed each Text into it’s own StackPane or another (perhaps more appropriate) subclass of Region to be able to provide an individually coloured background for each Text. And some of those Texts (especially the one in this example) should have a bi-colour background, both colours divided by the line from left bottom to right upper corner.
The simple solution would be to provide a background image. It’s not too difficult to produce one. But then, i have to produce a new background image for every pair of colours. I would prefer a more flexible solution.
All property setters and CSS properties i have found provide a one-colour-background. But sometimes i require bi-colour.
The proposed LineGradient would be acceptable if everything else fails. I would prefer a clear border between both colours, not a gradient.
Ok, i found a solution, at least for the simplified problem. Thanks to #kleopatra. As a path, i used a javafx.scene.shape.Polygon and filled it with the appropriate colour. Using aStackPane`, it is important to watch the z coordinate. Background naturally bottom, filled polyline as first content in the pane, and text on top.
public class DividedBackgroundDemo extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Test: Diagonally divided colour background");
Text txt = new Text("Text");
txt.setFont(Font.font("Arial", FontWeight.BOLD, FontPosture.REGULAR, 50));
Polygon triangle = new Polygon();
triangle.getPoints().addAll(new Double[] { 0.0, 0.0, 200.0, 0.0, 0.0, 200.0 });
triangle.setFill(Color.YELLOW);
StackPane root = new StackPane();
root.getChildren().add(triangle);
root.getChildren().add(txt);
root.setStyle("-fx-background-color: blue;");
primaryStage.setScene(new Scene(root, 200, 200));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Change postion of a line to make a gauge javafx

I want to make half radial gauge. I've tried to put an arc of 180° and I put a line on it, and I tried to move this line to use this as an indicator of position.
I tried to move the line to different position in Scene Builder and it appears that it could works but when I tried to move with code it doesn't.
private Scanner sc;
public void deplacement_aiguille(){
sc = new Scanner(System.in);
double angle = sc.nextDouble();
String valangle = Double.toString(angle);
valeur_gisement.setText(valangle);
float xfin = (float) ((Math.cos(angle))*200);
float yfin = (float) ((Math.sin(angle)*200));
if(angle<90){
gisement.relocate(5,10);
gisement.setEndX(xfin);
gisement.setEndY(-yfin);
}
if (angle>90){
gisement.relocate(6,10);
gisement.setEndX(xfin);
gisement.setEndY(yfin);
}
if(angle==90){
gisement.setEndX(0);
gisement.setEndY(200);
}
if(angle==180){
gisement.setEndX(200);
gisement.setEndY(0);
}
if(angle==0){
gisement.relocate(5,10);
gisement.setEndX(-200);
gisement.setEndY(0);
}
}
With this code I want to move the line in my gridpane to the column number 5 and row number 10 when my angle is smaller than 90 and to the column number 6 and row 10 when angle is bigger than 90
I'm not sure if it's the good way to do it. So if you have any better idea I'll take it. But if it's the good way to do it would you help me to make it works.
Thanks
I'd put the Arc and the Line in a Pane (for absolute positioning) and use a Rotate transform to move the line.
IMO More important is to bind the Rotate to the input value. In my example I use a Slider for it:
public class Gauge extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Arc arc = new Arc();
arc.setCenterX(100);
arc.setCenterY(0);
arc.setRadiusX(100);
arc.setRadiusY(100);
arc.setStartAngle(0);
arc.setLength(180);
arc.relocate(0, 0);
double lineCenterX = 100d;
double lineCenterY = 100d;
Line line = new Line(lineCenterX, lineCenterY, 0, 100);
line.setStroke(Color.YELLOW);
Rotate rotate = new Rotate();
rotate.setPivotX(lineCenterX);
rotate.setPivotY(lineCenterY);
line.getTransforms().add(rotate);
Pane pane = new Pane();
pane.getChildren().addAll(arc, line);
Slider slider = new Slider();
rotate.angleProperty().bind(slider.valueProperty().multiply(1.8));
VBox vbox = new VBox(10);
vbox.getChildren().addAll(pane, slider);
Scene scene = new Scene(vbox);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

JavaFX 2.X - Animated background and animated controls

A few days ago I started studying JavaFX, and came across the desire to perform 2 experiments. Firstly, I would like to know if it is possible to put an animated background behind an user interface. I've succeeded in creating an animated background, and now I'm having great difficulties to position some controls in the middle of my interface.
I'd like to introduce you 2 pictures of my program. The first demonstrates the undesirable result that I'm getting:
I believe this is my nodes tree:
This is the code of my application:
public class AnimatedBackground extends Application
{
// #########################################################################################################
// MAIN
// #########################################################################################################
public static void main(String[] args)
{
Application.launch(args);
}
// #########################################################################################################
// INSTÂNCIAS
// #########################################################################################################
private Group root;
private Group grp_hexagons;
private Rectangle rect_background;
private Scene cenario;
// UI
private VBox lay_box_controls;
private Label lab_test;
private TextArea texA_test;
private Button bot_test;
// #########################################################################################################
// INÍCIO FX
// #########################################################################################################
#Override public void start(Stage stage) throws Exception
{
this.confFX();
cenario = new Scene(this.root , 640 , 480);
this.rect_background.widthProperty().bind(this.cenario.widthProperty());
this.rect_background.heightProperty().bind(this.cenario.heightProperty());
stage.setScene(cenario);
stage.setTitle("Meu programa JavaFX - R.D.S.");
stage.show();
}
protected void confFX()
{
this.root = new Group();
this.grp_hexagons = new Group();
// Initiate the circles and all animation stuff.
for(int cont = 0 ; cont < 15 ; cont++)
{
Circle circle = new Circle();
circle.setFill(Color.WHITE);
circle.setEffect(new GaussianBlur(Math.random() * 8 + 2));
circle.setOpacity(Math.random());
circle.setRadius(20);
this.grp_hexagons.getChildren().add(circle);
double randScale = (Math.random() * 4) + 1;
KeyValue kValueX = new KeyValue(circle.scaleXProperty() , randScale);
KeyValue kValueY = new KeyValue(circle.scaleYProperty() , randScale);
KeyFrame kFrame = new KeyFrame(Duration.millis(5000 + (Math.random() * 5000)) , kValueX , kValueY);
Timeline linhaT = new Timeline();
linhaT.getKeyFrames().add(kFrame);
linhaT.setAutoReverse(true);
linhaT.setCycleCount(Animation.INDEFINITE);
linhaT.play();
}
this.rect_background = new Rectangle();
this.root.getChildren().add(this.rect_background);
this.root.getChildren().add(this.grp_hexagons);
// UI
this.lay_box_controls = new VBox();
this.lay_box_controls.setSpacing(20);
this.lay_box_controls.setAlignment(Pos.CENTER);
this.bot_test = new Button("CHANGE POSITIONS");
this.bot_test.setAlignment(Pos.CENTER);
this.bot_test.setOnAction(new EventHandler<ActionEvent>()
{
#Override public void handle(ActionEvent e)
{
for(Node hexagono : grp_hexagons.getChildren())
{
hexagono.setTranslateX(Math.random() * cenario.getWidth());
hexagono.setTranslateY(Math.random() * cenario.getHeight());
}
}
});
this.texA_test = new TextArea();
this.texA_test.setText("This is just a test.");
this.lab_test = new Label("This is just a label.");
this.lab_test.setTextFill(Color.WHITE);
this.lab_test.setFont(new Font(32));
this.lay_box_controls.getChildren().add(this.lab_test);
this.lay_box_controls.getChildren().add(this.texA_test);
this.lay_box_controls.getChildren().add(this.bot_test);
this.root.getChildren().add(this.lay_box_controls);
}
}
I've tried to make the use of a StackPane as the root of my scene graph, but also found an undesired result. Despite the controls have stayed in the center of the window, the circles begin to move in as they grow and shrink, making it appear that everything is weird.
The second thing I would like to know is if it is possible to customize the controls so they perform some animation when some event happens. Although we can change the appearance of controls using CSS, it's harder to create something complex. For example, when a control changes its appearance due to a change of state, the transition state change is not made in an animated way, but in an abrupt and static way. Is there a way to animate, for example, a button between its states? This would be done using the JavaFX API? Or would that be using CSS? Or would not be possible in any way?
Thank you for your attention.
after much struggle, I and some users of the Oracle community could resolve this issue. I see no need to repeat here all the resolution made ​​by us, so I'll post the link so you can access the solution of the problem. I hope this benefits us all. Thanks for your attention anyway.
https://community.oracle.com/thread/2620500

Resources