For the life of me, I can't seem to get help on this. I have a JavaFX screen and I am trying to get to show fullscreen on my 2nd monitor. I tried the following based on other recommendations but to no avail. I know the coordinates are right but it KEEPS going full screen on my MAIN monitor. Please help.
if (mainSet.getBoolean("fullScr", false)) {
int count = mainSet.getInt("MonSel", 0);
if (count > 0) {
int i = 0;
for (Screen screen: Screen.getScreens()) {
if (count == i) {
Rectangle2D bounds = screen.getBounds();
primaryStage.setX(bounds.getMinX());
System.out.println(bounds.getMinX());
System.out.println(bounds.getMinY());
primaryStage.setY(bounds.getMinY());
}
i++;
}
}
primaryStage.setFullScreen(true);
}
The first if checks a preference to see if fullscreen is set. the 2nd if sees if another monitor besides the first one was selected. It's 1, so that should be the 2nd monitor. The program loops through all screens and tries to move the program and THEN will go full screen. I know the coordinates are the same but no dice, it still goes full screen on the main screen. Please help.
I don't know if I truly understand your problem, but if you have two screens, why loop through the screens? Why not just use the info associated with the screen in position two/index one of the ObservableList? I am posting a sample app that demos how to display full screen on a second monitor.
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Screen;
import javafx.stage.Stage;
/**
*
* #author blj0011
*/
public class JavaFXApplication257 extends Application
{
#Override
public void start(Stage primaryStage)
{
ObservableList<Screen> screens = Screen.getScreens();//Get list of Screens
Button btn = new Button();
btn.setText("Full Screen - Screen 1");
btn.setOnAction((ActionEvent event) -> {
Rectangle2D bounds = screens.get(0).getVisualBounds();
primaryStage.setX(bounds.getMinX());
primaryStage.setY(bounds.getMinY());
primaryStage.setFullScreen(true);
//primaryStage.setWidth(bounds.getWidth());
//primaryStage.setHeight(bounds.getHeight());
});
Button btn2 = new Button();
btn2.setText("Full Screen - Screen 2");
btn2.setOnAction((ActionEvent event) -> {
if (screens.size() > 0) {
Rectangle2D bounds = screens.get(1).getVisualBounds();
primaryStage.setX(bounds.getMinX());
primaryStage.setY(bounds.getMinY());
primaryStage.setFullScreen(true);
//primaryStage.setWidth(bounds.getWidth());
//primaryStage.setHeight(bounds.getHeight());
}
});
StackPane root = new StackPane();
root.getChildren().add(new VBox(btn, btn2));
Scene scene = new Scene(root, 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);
}
}
Related
I am using CSS to configure my JavaFX Sliders, then applying the style in code with:
cssSlider.getStyleClass().add("slider-style");
When I first open my window, the tick marks are present on the CSS configured Slider(s). When I close and reopen the window, the tick marks are no longer present.
This following example demonstrates the anomaly using 2 Sliders, one configured directly, the other via CSS. Click the button to hide the window for 2 seconds. Notice that the Slider in which I directly configure the attributes works fine after hiding and re-showing, but the CSS configured Slider loses its tick marks after hiding and re-showing.
Does anyone have any ideas why showing, hiding, and re-showing the window causes the tick marks to vanish from the CSS configured Slider? Am I doing something wrong, or is this a JavaFX bug?
sample.css:
.slider-style {
-fx-show-tick-marks: true;
-fx-snap-to-ticks: true;
-fx-major-tick-unit: 5;
-fx-minor-tick-count: 5;
}
CssExample.java:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
/**
* This simple example demonstrates that JavaFX Sliders configured with CSS only show their tick marks the first time
* they are shown. If the Slider is hidden, then shown again, the tick marks are gone forever.
*/
public class CssExample extends Application {
#Override
public void start(Stage stage) throws InterruptedException, IOException {
Group root = new Group();
Scene scene = new Scene(root, 400, 200);
stage.setScene(scene);
stage.setTitle("Slider Sample");
scene.setFill(Color.BLACK);
GridPane grid = new GridPane();
grid.setPadding(new Insets(10, 10, 10, 10));
grid.setVgap(10);
grid.setHgap(70);
scene.setRoot(grid);
int rowNumber = 1;
Label directLabel = new Label("Slider from attribute assignment");
GridPane.setConstraints(directLabel, 1, rowNumber++);
grid.getChildren().add(directLabel);
Slider directSlider = new Slider();
GridPane.setConstraints(directSlider, 1, rowNumber++);
grid.getChildren().add(directSlider);
directSlider.setShowTickMarks(true);
directSlider.setSnapToTicks(true);
directSlider.setMajorTickUnit(5);
directSlider.setMinorTickCount(5);
Label cssLabel = new Label("Slider from CSS (tick marks disappear after hidden)");
GridPane.setConstraints(cssLabel, 1, rowNumber++);
grid.getChildren().add(cssLabel);
Slider cssSlider = new Slider();
GridPane.setConstraints(cssSlider, 1, rowNumber++);
grid.getChildren().add(cssSlider);
URL url = getClass().getResource("sample.css");
String cssString = url.toExternalForm();
scene.getStylesheets().add(cssString);
cssSlider.getStyleClass().add("slider-style");
Button button = new Button("Hide for 2 Seconds");
GridPane.setConstraints(button, 1, rowNumber++);
grid.getChildren().add(button);
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
stage.hide();
stage.show();
}
});
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
is this a JavaFX bug?
Yes.
See: https://github.com/openjdk/jfx/blob/fdc88341f1df8fb9c99356ada54b25124b77ea6e/modules/javafx.controls/src/main/java/javafx/scene/control/skin/SliderSkin.java#L398
It is a bug in the internal implementation of the setShowTickMarks method of SliderSkin (verified in JavaFX 18.0.1).
Test case:
import javafx.animation.PauseTransition;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Slider;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.io.IOException;
public class CssExample extends Application {
private static final String CSS = // language=CSS
"""
.slider-style {
-fx-show-tick-marks: true;
-fx-snap-to-ticks: true;
-fx-major-tick-unit: 5;
-fx-minor-tick-count: 5;
}
""";
private static final String CSS_INLINE = "data:text/css," + CSS;
#Override
public void start(Stage stage) throws InterruptedException, IOException {
Platform.setImplicitExit(false);
Slider cssSlider = new Slider();
cssSlider.showTickMarksProperty().addListener((observable, oldValue, newValue) ->
System.out.println(cssSlider.showTickMarksProperty())
);
cssSlider.getStyleClass().add("slider-style");
PauseTransition hideAnimation = new PauseTransition(Duration.seconds(2));
hideAnimation.setOnFinished(e -> stage.show());
Button hideWindow = new Button("Hide for 2 Seconds");
hideWindow.setOnAction(e -> {
stage.hide();
hideAnimation.play();
});
Button closeApp = new Button("Close app");
closeApp.setOnAction(e -> Platform.exit());
VBox layout = new VBox(
10,
cssSlider, hideWindow, closeApp
);
layout.setPadding(new Insets(10));
layout.setPrefSize(400, 120);
Scene scene = new Scene(layout);
scene.getStylesheets().add(CSS_INLINE);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Test output:
BooleanProperty [bean: Slider#132908b9[styleClass=slider slider-style], name: showTickMarks, value: true]
BooleanProperty [bean: Slider#132908b9[styleClass=slider slider-style], name: showTickMarks, value: false]
BooleanProperty [bean: Slider#132908b9[styleClass=slider slider-style], name: showTickMarks, value: true]
It switches showTicks from true to false, and back to true, which triggers the bug.
In the current implementation for the setShowTicks method:
private void setShowTickMarks(boolean ticksVisible, boolean labelsVisible) {
showTickMarks = (ticksVisible || labelsVisible);
Slider slider = getSkinnable();
if (showTickMarks) {
if (tickLine == null) {
tickLine = new NumberAxis();
tickLine.setAutoRanging(false);
tickLine.setSide(slider.getOrientation() == Orientation.VERTICAL ? Side.RIGHT : (slider.getOrientation() == null) ? Side.RIGHT: Side.BOTTOM);
tickLine.setUpperBound(slider.getMax());
tickLine.setLowerBound(slider.getMin());
tickLine.setTickUnit(slider.getMajorTickUnit());
tickLine.setTickMarkVisible(ticksVisible);
tickLine.setTickLabelsVisible(labelsVisible);
tickLine.setMinorTickVisible(ticksVisible);
// add 1 to the slider minor tick count since the axis draws one
// less minor ticks than the number given.
tickLine.setMinorTickCount(Math.max(slider.getMinorTickCount(),0) + 1);
if (slider.getLabelFormatter() != null) {
tickLine.setTickLabelFormatter(stringConverterWrapper);
}
getChildren().clear();
getChildren().addAll(tickLine, track, thumb);
} else {
tickLine.setTickLabelsVisible(labelsVisible);
tickLine.setTickMarkVisible(ticksVisible);
tickLine.setMinorTickVisible(ticksVisible);
}
}
else {
getChildren().clear();
getChildren().addAll(track, thumb);
// tickLine = null;
}
getSkinnable().requestLayout();
}
The first time it shows the ticks it will do this:
getChildren().clear();
getChildren().addAll(tickLine, track, thumb);
Then, when the ticks are hidden, it will do this:
getChildren().clear();
getChildren().addAll(track, thumb);
Then, when the ticks are supposed to be shown again, the tickLine is not added back to the children, so it never shows the ticks again.
This program first displays a bullseye created by three different sized circles.
Once the animate me button is clicked, the function animation() will make the existing circles shrink inwards until the size of the circles is zero.
Once the user presses the button named "Press to stop", the animation will then stop. If the user presses the button again, it will then keep going from the state it was stopped from, so on so forth.
Currently, this is not working as intended. It only creates about 9 circles (including the nine circles that the program began with). I know I will need to use the action listener in order to make the program run, but I'm having a hard time in terms of the documentation of the action listener. What am I supposed to put in the parameters of the listener? If you see any other ways around this, please feel free to let me know.
package target;
import javafx.animation.ScaleTransition;
import javafx.animation.Timeline;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Target extends Application
{
Circle[] cir = new Circle[7];
Button btn = new Button("Animate me!");
StackPane root = new StackPane();
public static void main(String[] args)
{
launch(args);
}
/**
* start method will create the target and the start button first
* displayed on-screen to the user
*/
#Override
public void start(Stage primaryStage)
{
root.setStyle("-fx-border-color:black;");
cir[0] = new Circle(400, 250, 200);
cir[0].setFill(Color.RED);
cir[0].setStyle("-fx-border-color:black;");
cir[1] = new Circle(315, 165, 115);
cir[1].setFill(Color.WHITE);
cir[1].setStyle("-fx-border-color:black;");
cir[2] = new Circle(230, 80, 30);
cir[2].setFill(Color.RED);
cir[2].setStyle("-fx-border-color:black;");
root.getChildren().addAll(cir[0], cir[1], cir[2]);
root.getChildren().add(btn);
primaryStage.setScene(new Scene(root));
primaryStage.show();
btn.setOnAction(e ->
{
animation();
btn.setText("Press to Stop");
});
}
public void animation()
{
//Timeline animation = new Timeline(
//)
ScaleTransition[] st = new ScaleTransition[7];
boolean recycleCircles = false;
st[0]= new ScaleTransition(Duration.seconds(7), cir[0]);
st[0].setToX(0.0f);
st[0].setToY(0.0f);
st[0].play();
st[1] = new ScaleTransition(Duration.seconds(5.5), cir[1]);
st[1].setToX(0.0f);
st[1].setToY(0.0f);
st[1].play();
st[2] = new ScaleTransition(Duration.seconds(4), cir[2]);
st[2].setToX(0.0f);
st[2].setToY(0.0f);
st[2].play();
// int delayInc = 1;
int delay = 1;
//will create circles (will rotate between white and red) and then add
//to scaleTransitions
//while(btn.isPressed() == false)
{
for(int i = 3; i<st.length; i++)
{
if(recycleCircles == true)
{
i = 0;
recycleCircles = false;
}
if(i % 2 == 1)
{
cir[i] = new Circle(400,250,200);
cir[i].setFill(Color.WHITE);
cir[i].setStyle("-fx-border-color:black;");
root.getChildren().add(cir[i]);
cir[i].toBack();
st[i] = new ScaleTransition(Duration.seconds(7), cir[i]);
st[i].setDelay(Duration.seconds(delay));
delay++;
st[i].setToX(0.0f);
st[i].setToY(0.0f);
st[i].play();
}
else if(i%2==0)
{
cir[i] = new Circle(400, 250, 200);
cir[i].setFill(Color.RED);
cir[i].setStyle("-fx-border-color:black;");
root.getChildren().add(cir[i]);
cir[i].toBack();
st[i] = new ScaleTransition(Duration.seconds(7), cir[i]);
st[i].setDelay(Duration.seconds(delay));
delay++;
st[i].setToX(0.0f);
st[i].setToY(0.0f);
st[i].play();
}
if(i == 6)
recycleCircles = true;
}
}
//btn.pressedProperty().addListener(listener);
btn.setOnMousePressed(event ->
{
});
btn.setOnMouseReleased(event ->
{
for(int y = 0; y<st.length;y++)
{
}
});
}
}
Not sure whether you have any specific use case with each circle. If your are using the circles only for the purpose of alternating row colors, then you can get similar effect with radial gradient's repeat option.
To the extent I understand the question, below program is what I can think of. May be this can help you.
Just to let you know, the overall effect is slightly different from your program. The main difference in effects is, your program gives an effect/impression that each circle are shrinking towards center, as the distance between each circle is always same till it shrinked completely.
My program gives the effect/.impression like the entire board is moving away from your sight till it vanishes. In my program the distance between each circle decreases proportianally till it shrinks.
import javafx.animation.ScaleTransition;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class TargetAnimation extends Application {
Button btn = new Button("Animate me!");
StackPane root = new StackPane();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
root.setPrefSize(400, 400);
root.setStyle("-fx-border-color:black;");
Circle board = new Circle();
board.setRadius(200);
board.setStyle("-fx-fill:radial-gradient(focus-angle 0deg , focus-distance 0% , center 50% 50% , radius 21% , repeat, red 44% , white 46% );-fx-stroke-width:1px;-fx-stroke:black;");
root.getChildren().addAll(board, btn);
primaryStage.setScene(new Scene(root));
primaryStage.show();
ScaleTransition transition = new ScaleTransition(Duration.seconds(7), board);
transition.setToX(0);
transition.setToY(0);
btn.setOnAction(e -> {
switch (transition.getStatus()) {
case RUNNING:
transition.pause();
break;
case PAUSED:
transition.play();
break;
default:
board.setScaleX(1);
board.setScaleY(1);
transition.playFromStart();
}
});
}
}
The code given to setOnAction is an EventHandler, which is a #FunctionalInterface with the single method handle. That means that you can give it a lambda expression instead. The method takes an argument, which is the ActionEvent of clicking the button (created for you by JavaFX), and runs the code you give it.
If you want to pause the animation, call Animation#pause, and if you want to resume it, call Animation#play. I suggest that you create a ParallelTransition with all of your ScaleTransitions as its children. Then call the above methods on the ParallelTransition in the event handler.
That means that the setup code, like naming the button and creates the animations, goes outside of the event handler.
I have not been able to find any good questions regarding my predicament. I am trying to count/check how many times a specific item is clicked via an actionListener but am unsure of how to use an actionListener/EventHandler to document the click. This is being done in JavaFX.Pardon the potentially noobish question.
correctUrl = getCorrectUrl(); //Correct image for set
wrongUrl = getWrongUrl();
initialPos(); //everything is placed into default.
imageOne.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
imageOne.setOnMouseClicked((MouseEvent e) -> {
imageOne = flipToCard(imageOne, 1);
});
returnCardOne();
System.out.println("Tile pressed ");
event.consume();
});
The ultimate goal of the code is to notice two images have been clicked and then check to see if their URL == each-other.
If the URLs are equal, the Images should be equal. So why not compare Images? This little app demos what you are trying to achieve. Comments in the code.
Main:
import java.util.ArrayList;
import java.util.List;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javafx.util.Duration;
/**
*
* #author Sedrick
*/
public class JavaFXApplication51 extends Application {
#Override
public void start(Stage primaryStage) {
List<ImageViewTile> imageViews = new ArrayList();
List<ImageViewTile> cardsBeingMatched = new ArrayList();//Used to keep up with the current two cards that are pressed inorder to deteremine if they are a match
Image initialImage = new Image(getClass().getResourceAsStream("cardBack_blue1.png"));
Image ace = new Image(getClass().getResourceAsStream("cardSpadesA.png"));
Image king = new Image(getClass().getResourceAsStream("cardSpadesK.png"));
imageViews.add(new ImageViewTile(initialImage, ace));
imageViews.add(new ImageViewTile(initialImage, king));
imageViews.add(new ImageViewTile(initialImage, ace));
imageViews.add(new ImageViewTile(initialImage, king));
for(ImageViewTile view : imageViews)
{
//Set ImageViews' onMouseClicked handler
view.setOnMouseClicked(event->{
if(!view.isShowing())//If card face value is not showing
{
view.showFrontImage();//show it.
cardsBeingMatched.add(view);//Add card being clicked to list so it can be compared against the next card
if(cardsBeingMatched.size() == 2)//Once two cards are in the list, see if they are equal.
{
if(cardsBeingMatched.get(0).getImage().equals(cardsBeingMatched.get(1).getImage()))//If cards are equal a match is found
{
System.out.println("Match");
cardsBeingMatched.clear();//clear the list to prepare to compare the next two cards that are clicked
}
else//If cards are not equal
{
System.out.println("No match");
//wait half a second and flip cards back over
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(.5), (event1) -> {
System.out.println(".5 seconds need to pass before another mouse click!");
}));
timeline.setCycleCount(1);
timeline.play();
timeline.setOnFinished(event1->{
cardsBeingMatched.get(0).showBackImage();
cardsBeingMatched.get(1).showBackImage();
cardsBeingMatched.clear();//clear the list to prepare to compare the next two cards that are clicked
});
}
}
}
});
}
GridPane root = new GridPane();
for(int i = 0; i < imageViews.size(); i++)
{
root.add(imageViews.get(i), i % 2, i / 2);//Add ImageViews to the GridPane
}
Scene scene = new Scene(root, 280, 380);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
ImageViewTitle Class:
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
/**
*
* #author Sedrick
*/
public final class ImageViewTile extends ImageView{
private boolean showing;
private final Image backImage;
private final Image frontImage;
public ImageViewTile(Image backImage, Image frontImage) {
this.backImage = backImage;
this.frontImage = frontImage;
this.setImage(backImage);
showing = false;
}
public void showBackImage()
{
this.setImage(backImage);
showing = false;
}
public void showFrontImage()
{
this.setImage(frontImage);
showing = true;
}
public boolean isShowing()
{
return showing;
}
}
I created this class to help me keep up with the ImageView's different states.
I have a SplitMenuButton, and I can't seem to find a way to trigger an event when the user clicks the arrow next to the button.
I would like the dropdown to fill with items from a database when the dropdown arrow is clicked.
I am not sure which event can do that, and I can not find any info on this either.
Short answer: register a listener with the showing property.
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.scene.Scene;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SplitMenuButton;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class SplitMenuButtonTest extends Application {
#Override
public void start(Stage primaryStage) {
IntegerProperty count = new SimpleIntegerProperty();
SplitMenuButton splitMenuButton = new SplitMenuButton();
splitMenuButton.setText("Action");
splitMenuButton.showingProperty().addListener((obs, wasShowing, isNowShowing) -> {
if (isNowShowing) {
int c = count.get() + 1;
count.set(c);
splitMenuButton.getItems().clear();
for (int choice = 1; choice <= 3; choice++) {
MenuItem mi = new MenuItem("Choice "+choice+" (" + c + ")");
splitMenuButton.getItems().add(mi);
}
}
});
BorderPane root = new BorderPane(null, splitMenuButton, null, null, null);
primaryStage.setScene(new Scene(root, 350, 150));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Sort of as an aside, I'm not sure this is a really good idea. Database connections are typically long-running processes (i.e. long enough to be visually noticeable in a UI environment). If you run this on the FX Application Thread, then you're going to block the UI from doing anything while the data is retrieved, and that's also right at the moment the user has just tried to do something. Of course, if you run it as a background task, then the menu will popup with the previous data, and then later update once the data is downloaded. I would recommend finding a way to populate this before the user requests it.
The 'arrow' is just another button used to show the popup with the menu items.
One easy way of knowing if this arrow button is pressed is by listening to the showing property of the popup.
Once you know that the popup is showing up, you can add your items.
#Override
public void start(Stage primaryStage) {
SplitMenuButton m = new SplitMenuButton();
m.showingProperty().addListener((ov,b,b1)->{
if(b1){
System.out.println("popup visible");
MenuItem menuItem = new MenuItem("New Option");
if(m.getItems().stream().noneMatch(i->i.getText().equals(menuItem.getText()))){
menuItem.setOnAction(e -> System.out.println("New Option added"));
m.getItems().add(menuItem);
}
}
});
m.setText("Click the arrow ->");
m.getItems().add(new MenuItem("First option"));
StackPane root = new StackPane(m);
Scene scene = new Scene(root, 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
I have to create a "slot machine effect": I have a root layer an on it I have 3 Rectangles, each one in a TilePane cell. i tryed to add an event handler that should modify the rect (resizing it and rotating it) in order to change the figure that it displays. Unfortunately, my figure is never at the center fo its cell. How can I fix it?
package test;
import java.util.Random;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.TilePane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
/**
*
* #author bog
*/
public class Test extends Application {
StackPane root = new StackPane();
TilePane tp = new TilePane(Orientation.HORIZONTAL);
#Override
public void start(Stage primaryStage) {
//root.getChildren().add(btn);
for(int i = 0; i < 3 ; i++){
final Rectangle r = new Rectangle(100, 100, Color.GREY);
r.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
Random rnd = new Random();
int n = rnd.nextInt(5);
if(n == 0){ // horizontal line
r.setWidth(100);
r.setHeight(5);
System.out.println("Linea orizontale");
}
if(n == 1){ // vertical line
r.setWidth(5);
r.setHeight(100);
System.out.println("Linea verticale");
}
if(n == 2){ // rombo
r.getTransforms().add(new Rotate(45,50,50));
System.out.println("rombo");
}
if(n == 3){ // back-slash line
r.setWidth(5);
r.setHeight(100);
r.getTransforms().add(new Rotate(45,50,50));
System.out.println("Linea /");
}
if(n == 4){ // slash line
r.setWidth(100);
r.setHeight(5);
r.getTransforms().add(new Rotate(45,50,50));
System.out.println("Linea \\");
}
}
});
final StackPane sp = new StackPane();
sp.getChildren().add(r);
tp.getChildren().add(sp);
}
tp.setAlignment(Pos.CENTER);
root.getChildren().add(tp);
Scene scene = new Scene(root, 500, 450);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
i am not quite sure what is your problem , and right now i cant test your code , but almost every time i got alignment issues i fix them with scene builder, where i create the static components by hand , which will be rendered allright , and inside them i place the dynamic components. So your pane could be made from scene builder starting with a basic anchor pane and inside it place 3 panes with your default width, and inside them dynamically add the images you wish each time.
hope it helps...