How to manage element precedence in JavaFX2? - user-interface

Given this code:
#Override
public void start(final Stage stage)
{
final StackPane root = new StackPane();
final Region r1 = new Region(), r2 = new Region(), r3 = new Region();
r1.setMaxSize(400, 400);
r1.setStyle("-fx-background-color: yellow");
StackPane.setAlignment(r1, Pos.TOP_LEFT);
r2.setMaxSize(400, 400);
r2.setStyle("-fx-background-color: black");
StackPane.setAlignment(r2, Pos.TOP_RIGHT);
r3.setMaxSize(400, 400);
r3.setStyle("-fx-background-color: blue");
StackPane.setAlignment(r3, Pos.BOTTOM_CENTER);
root.getChildren().addAll(r1, r2 ,r3);
final Scene scene = new Scene(root, 600, 600);
stage.setScene(scene);
stage.show();
}
The output is the following:
Is there any easy way to control element precedence, without removing and re-adding all the elements that follow in the correct order? What I want to do, in this particular case, is make the element with the yellow background to overlay the other two, thus resulting in this:
The Scene Builder can move elements with CTRL+([|]). The only way that I can think of currently though, when it comes to doing this in code, is getting the children of the root element and doing pairs of remove/add in the correct order. Is there any other way, like, maybe, some property that manages overlay priority? Thank you.

Related

Rotation through images using JAVA FX

Essentially I'm trying to make a glowing warning image.
Starts just being a red triangle, but then emits a glow, then goes back to a red triangle.
But I'm trying to figure out a way to implement it.
I thought of using timelines, but it will only show the last picture, and stay on it.
I've replaced my Imaged with ones publicly available.
With these images it should come up "Number 1" for 2 seconds, "Number 2" for 2 seconds, "number 3" for 2 seconds, then go back to number 1 and repeat indefinitely.
Other than my way, if someone has a better way to make my objective happen in a different way with Java FX (That isn't too complex, I'm pretty new to Java FX). I'm all ears
Thanks again!
Here is the code I've fiddled with.
public class GlowEffect extends Application {
#Override
public void start(Stage primaryStage) {
Image img1 = new Image("http://clipart-library.com/images/dc9rEEbdi.jpg");
Image img2 = new Image("http://clipart-library.com/data_images/356167.png");
Image img3 = new Image("http://clipart-library.com/data_images/123556.png");
ImageView imgview1 = new ImageView();
imgview1.setX(0);
imgview1.setY(0);
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds(2), e -> imgview1.setImage(img1)),
new KeyFrame(Duration.seconds(2), e -> imgview1.setImage(img2)),
new KeyFrame(Duration.seconds(2), e -> imgview1.setImage(img3))
);
timeline.setCycleCount(Animation.INDEFINITE);
Pane pane = new Pane(imgview1);
Scene scene = new Scene(pane, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
timeline.play();
}
public static void main(String[] args) {
launch(args);
}
}

Javafx relocate and rotate

i have an node in javafx which are moving in a timeline.
Now i want rotate the node also.
I tried it but everytime the node doesn't hold the path anymore and "fly away". Is there a way to relcate and rotate (I tried it with rotatetransition)?
Edit:
That is my View -Class
public class MyView extends ImageView{
public MyView (Image image) {
super(image);
RotateTransition transition = new RotateTransition();
transition.setCycleCount(Animation.INDEFINITE);
transition.setNode(this);
transition.setDuration(Duration.millis(10));
transition.setFromAngle(5);
transition.setToAngle(5;
transition.setAutoReverse(true);
transition.play(); // */
}
}
On another class i have this:
private void startMoveAnimation(MyView[] views) {
x++;
y++;
this.timeline = new Timeline();
timeline.setCycleCount(Animation.INDEFINITE);
moveEvent = new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
for(View view: views){
view.relocate(x,y);
}
}
}
};
KeyFrame moveKeyFrame = new KeyFrame(Duration.millis(SPEED), moveEvent);
timeline.getKeyFrames().add(moveKeyFrame);
timeline.play(); // */
}
x and y are double values.
Using transforms gives you better control of the order of the transformations. Furthermore some transfroms allow you to specify a pivot point, which is not possible for e.g. the Node.rotate property. Transforms in a list are applied "right to left". (The transform with the highest index is applied first).
The following example shows how to move a rectangle rotating arount its own center (even though the cycle resets to the original position instead of continuously moving in the same direction, but the properties of the transforms can be animated independently in arbitrary ways):
#Override
public void start(Stage primaryStage) {
Rectangle view = new Rectangle(100, 100);
// pivot point = center of rect
Rotate rotate = new Rotate(0, 50, 50);
Translate translate = new Translate();
// rotate first, then move
view.getTransforms().addAll(translate, rotate);
Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(translate.xProperty(), 0d),
new KeyValue(translate.yProperty(), 0d), new KeyValue(rotate.angleProperty(), 0d)),
new KeyFrame(Duration.seconds(2), new KeyValue(translate.xProperty(), 300d),
new KeyValue(translate.yProperty(), 500d), new KeyValue(rotate.angleProperty(), 360d)));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
Pane root = new Pane(view);
Scene scene = new Scene(root, 500, 500);
primaryStage.setScene(scene);
primaryStage.show();
}
That's what I would try first:
Put the node into a Group. Add the Group to the parent instead of the node. Do the translate animation on the Group and do the rotate animation on the node itself. This is just a first guess which I cannot try out because you haven't provided a minimal reproducible example.

How to change CURSOR to busy and prevent user clicking

I have three COMBO BOXES in my window. It is a family tree application I am developing using JavaFX and SQLIte. Each person has Father, Mother and Spouse info which can be selected from ComboBoxes. ComboBoxes are loaded with data from database.
It takes a while to load these three combo boxes. Actually different delays for different combo boxes.
If I click on a combo box while it is not ready or another combo box is not ready, the screen turns white until the other combo box is ready.
I want to prevent user input on entire window from Mouse, Keyboard and Buttons until entire window is ready to accept user's input. Until then I want change the cursor to something like STOP.
How to do this? Any suggestions?
Thanks,
Hornigold
Run a Task<ObservableList<SomeType>> (or a Task returning some object containing more than a single list) on a seperate Thread. Before starting the thread you disable the root and set the cursor for the scene and when the task finishes you initialize the GUI with the results and reenable the scene again:
#Override
public void start(Stage primaryStage) {
Button loadButton = new Button("load");
ComboBox<String> combo = new ComboBox<>();
VBox root = new VBox(combo, loadButton);
Scene scene = new Scene(root);
loadButton.setOnAction(evt -> {
root.setDisable(true);
// save old cursor to restore after finishing the task
final Cursor oldCursor = root.getScene().getCursor();
scene.setCursor(Cursor.WAIT);
Task<ObservableList<String>> task = new Task<ObservableList<String>>() {
#Override
protected ObservableList<String> call() throws Exception {
ObservableList<String> result = FXCollections.observableArrayList();
for (int i = 0; i < 100; i++) {
result.add(Integer.toString(i));
}
// simulate delay
Thread.sleep(5000);
return result;
}
};
task.setOnSucceeded(e -> {
// use results of task in the GUI
combo.setItems(task.getValue());
// restore cursor and reenable scene
root.setDisable(false);
scene.setCursor(oldCursor);
});
task.setOnFailed(e -> {
// todo: handle exception in Task.call
});
Thread thread = new Thread(task);
thread.start();
});
primaryStage.setScene(scene);
primaryStage.show();
}

Add Image dynamically in runtime - Unity 5

In my unity based Android game I wish to add the image dynamically based on the number of questions in each level. The image is shown for reference. Each correct answer will be marked in green and the wrong one in red. I am new to unity and trying hard to find steps to achieve this.
Any help with an example for this requirement will be a great help.
I once wrote a script for dynamically creating buttons based on each level. What I did was creating the first button on the scene and adding the other buttons based on the first one. Below is the shell of my code:
// tutorialButton and levelButtons are public variables which can be set from Inspector
RectTransform rect = tutorialButton.GetComponent<RectTransform> ();
for (int i = 1; i < levelSize; i++) {
// Instantiate the button dynamically
GameObject newButton = GameObject.Instantiate (tutorialButton);
// Set the parent of the new button (In my case, the parent of tutorialButton)
newButton.transform.SetParent (levelButtons.transform);
//Set the scale to be the same as the tutorialButton
newButton.transform.localScale = tutorialButton.transform.localScale;
//Set the position to the right of the tutorialButton
Vector3 position = tutorialButton.transform.localPosition;
position.x += rect.rect.width*i;
newButton.transform.localPosition = position;
}
I am not exactly sure if this is the right approach as it may or may not give unexpected results depending on different screen sizes and your canvas, but hopefully it gives you an idea about dynamically creating objects.
I'm not sure if this helps, but if you have all the images in the scene under a canvas, with this you just need to drag the canvas on the script and use
//level-1 is to keep the array notation
FindObjectOfType<NameOfScript>.ChangeColor(level-1,Color.green);
or you can do also
//level-1 is to keep the array notation
FindObjectOfType<NameOfScript>.RevertColor(level - 1);
This is the script:
//Keep it private but you still see it in inspector
//#Encapsulation :)
[SerializeField]
private Canvas _canvas;
private Image[] _images;
//keep the original colors in case you want to change back
private Color[] _origColors;
void Start () {
_images = GetComponentsInChildren<Image>();
_origColors = new Color[_images.Length];
for (int i = 0; i < _images.Length; i++)
{
_origColors[i] = _images[i].color;
}
}
//Reverts the color of the image back to the original
public void RevertToOriginal(int imageIndex)
{
_images[imageIndex].color = _origColors[imageIndex];
}
//Change to color to the coresponding index, starts from 0
public void ChangeColor(int imageIndex, Color color)
{
_images[imageIndex].color = color;
}
P.S If you want it visible only at the end you can make a method where you enable = (true or false) for the canvas. So you keep it false till the end of the level and you make it true when you want to show, while after every answer you call the ChangeColor depending on the result.
To make it easier you can use:
NameOfScript variableName = FindObjectOfType<NameOfScript>();
and after that you just call
variableName.ChangeColor(level - 1, Color.green);
Also it does not matter where you put the script. I would make some kind of manager(empty GameObject) in the scene and put it there.

How can I load Computer Directory images in JAVAFX

I am trying to load my computer folder images into a wall of thumbnails. I read on a thread from another forum that ImageView "url" instance variable does not support system paths. I tried with the solution there, but it throws an exception: java.lang.OutOfMemoryError: Java heap space as it keeps reading the file.
another problem is it keeps giving me warning of using package javafx.ext -> SwingUtils.toFXImage method.
I have also tried to input the URL like that:
"file://localhost//Users/USER/Pictures/Camera/test/1.JPG"
I tried to display a number of images, but it always only displays 3 to 4 images.
I checked with the error function given from ImageView, it does not indicate that the reading of my images encountered an error.
Are there any alternatives?
Code
function load() {
println("RUNTIME {Runtime.getRuntime().maxMemory()}");
System.gc();
Runtime.getRuntime().freeMemory();
//MAC Folder PATH
var path: String = "/Users/username/Pictures/camera/test/1.JPG";;
var file: File = new File(path);
//http://download.oracle.com/docs/cd/E17802_01/javafx/javafx/1.3/docs/api/javafx.ext.swing/javafx.ext.swing.SwingUtils.html
//public toFXImage(image: java.awt.image.BufferedImage) : Image
//Creates a JavaFX Image from a BufferedImage.
img = SwingUtils.toFXImage(ImageIO.read(file));
}
It is not clear exactly what you are trying to do. If you are talking about JavaFX 2.0, the following code works. If you are loading a lot of images and need to conserve memory, you only have to create enough ImageView's for the number you want to display at one time. Then as you page through the images, you can swap out the Image object contained in the ImageView.
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World");
StackPane root = new StackPane();
Scene scene = new Scene(root, 300, 250);
File file = new File("/System/Library/CoreServices/loginwindow.app/Contents/Resources/LogOut.png");
Image image = new Image(file.toURI().toString());
ImageView iv = new ImageView(image);
root.getChildren().add(iv);
primaryStage.setScene(scene);
primaryStage.show();
}
its simple: open a image with a browser and copy the whole url of the pic and paste it as a parameter of the Image object. DO NOT REMOVE "file///:" because this makes the image loadable. you will get your other logic from there. happy coding e.g
Image image = new Image("file:///C:/Users/Nigel/Desktop/my_image.png");
ImageView imgview = new ImageView(image);
None of the previous answers worked for me. However, this one, which I saw a while back but can't find an original link from, works flawlessly.
#Override
public void start(Stage primaryStage) throws Exception {
//create a pane to hold the image views
Pane pane = new HBox(10);
pane.setPadding(new Insets(5,5,5,5));
//create the image to be used!
Image image = new Image("/Content/vortex.jpg");
//set some custom properties and add an image
ImageView imageView = new ImageView(image);
imageView.setFitHeight(100);
imageView.setFitWidth(100);
pane.getChildren().add(imageView);
//add the second image view with this image and no custom properties
pane.getChildren().add(new ImageView(image));
ImageView imageView2 = new ImageView(image);
imageView2.setRotate(45);
pane.getChildren().add(imageView2);
Scene scene = new Scene(pane, 200, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
The key is that when you create the image, START the path with a '/' (ie: "/Content/vortex.jpg"). Note that in this setup, the root folder is the src folder in most IDEs.
sorry if my answer came a little bit late but that was my approach and it works 100% wherever you are putting your file
1.assign your image to File
2.parse the File to URI
3.assign the uri.toString() to the image
ex code:
File imageFile = new File("path/to/image/outside/your/jar/awesomeless.jpg");
String fileLocation = imageFile.toURI().toString();
Image fxImage = new Image(fileLocation);
or you can simply put it all together like this:
Image fxImage = new Image(new File("path/.../awesomemore.jpg").toURI().toString());
and please if anyone knows a better approach let us know!
Another solution is to pass the InputStream into the Image class constructor; and is working...
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World");
StackPane root = new StackPane();
Scene scene = new Scene(root, 300, 250);
java.io.FileInputStream fis = new FileInputStream("/System/Library/CoreServices/loginwindow.app/Contents/Resources/LogOut.png");
ImageView iv = new ImageView(new Image(fis));
root.getChildren().add(iv);
primaryStage.setScene(scene);
primaryStage.show();
}

Resources