Javafx label not updating after input from TextField in another scene - javafx

I have a label called test that is supposed to display the input value from TextField in the textInput class, from another scene. the value is being sent over to the main class but the label is not updating unless i click the button to go to the dialog box from textInput.
package javafx11;
import application.textInput;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextInputDialog;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
public class Main extends Application {
Stage window = new Stage();
Scene s1;
Scene s2;
Label test;
String input;
Button btn;
#Override
public void start(Stage primaryStage)throws Exception {
window=primaryStage;
VBox layout = new VBox();
s1= new Scene(layout,500,500);
test = new Label("This is where your text will appear");
btn = new Button("Click me");
window.setTitle("Dummy program");
layout.setAlignment(Pos.CENTER);
window.setScene(s1);
window.show();
btn.setOnAction(e -> {
input = textInput.textInput("title", "mnessage");
test.setText(input);
window.setScene(s1);
System.out.println(input);
});
layout.getChildren().addAll(test, btn);
}
public static void main(String[] args) {
launch(args);
}
}
the text input class:
package application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.TextInputDialog;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class textInput {
static String input;
public static TextField userField;
public static String textInput(String title, String message) {
Stage window = new Stage();
VBox layout = new VBox();
window.setTitle(title);
window.initModality(Modality.APPLICATION_MODAL);
Button btn = new Button("Click me to go back");
userField = new TextField();
Scene s1 = new Scene(layout, 500, 500);
window.setScene(s1);
layout.getChildren().add(btn);
layout.getChildren().add(userField);
btn.setOnAction(e ->{
input = userField.getText();
window.close();
System.out.println(input);
});
layout.setAlignment(Pos.CENTER);
window.show();
return input;
}
}
I tried googling it but i cant really seem to understand the solution provided by others.

Its all good, figured it out after tinkering with it a little longer.
in the main class, i had to change window.show(); to window.showAndWait();

Related

JavaFX - making Timeline object on multiple objects execute EventHandler once

I am working in JavaFX right now, and have run into a problem. I created a simple example to demonstrate the issue I am facing.
My issue is, I have a Timeline object setup on multiple anonymous Circle objects and I want an action to happen after the Timeline has finished its play() method. To do this, I setup a setOnFinished event handler to execute something after the animation has finished playing, However, it is executing this logic multiple times because it is working on multiple objects.
Here I have a simple program that adds 3 anonymous objects to a VBox and there is a button that will call the flash() method to start a Timeline animation on the circles.
package sample;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
VBox root = new VBox();
VBox circles = new VBox();
Button btn = new Button("Touch me to make me flash ;)");
btn.setOnAction(e -> flash(circles));
for(int i = 0; i < 3; i++) {
circles.getChildren().add(new Circle(25, Color.RED));
}
circles.setSpacing(10);
circles.setAlignment(Pos.CENTER);
root.getChildren().addAll(circles, btn);
root.setSpacing(10);
root.setAlignment(Pos.CENTER);
primaryStage.setScene(new Scene(root, 500, 500));
primaryStage.show();
}
private void flash(VBox root) {
for(Node circle : root.getChildren()) {
final Circle c = (Circle) circle;
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds(0.5), e -> c.setFill(Color.GOLD)),
new KeyFrame(Duration.seconds(1.0), e -> c.setFill(Color.RED))
);
timeline.setCycleCount(5);
timeline.play();
timeline.setOnFinished(e -> System.out.println("Do something here"));
}
}
}
You can see in the flash() method that there is an EventHandler that executes this line of code:
System.out.println("Do something here")
I want it to only be executing one time, but it executes 3 times because the Timeline object is setup on 3 circles.
How can I make it so the EventHandler only executes one time?
Consider using one TimeLine object for all Circle objects:
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application {
private ObjectProperty<Paint> colorProperty;
#Override
public void start(Stage primaryStage) throws Exception{
colorProperty = new SimpleObjectProperty<>(Color.WHITE);
VBox root = new VBox();
VBox circles = new VBox();
Button btn = new Button("Touch me to make me flash ;)");
btn.setOnAction(e -> flash(circles));
for(int i = 0; i < 3; i++) {
circles.getChildren().add(new Circle(25, Color.RED));
}
circles.setSpacing(10);
circles.setAlignment(Pos.CENTER);
root.getChildren().addAll(circles, btn);
root.setSpacing(10);
root.setAlignment(Pos.CENTER);
primaryStage.setScene(new Scene(root, 500, 500));
primaryStage.show();
}
private void flash(VBox root) {
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds(0.5), e -> colorProperty.set(Color.GOLD)),
new KeyFrame(Duration.seconds(1.0), e -> colorProperty.set(Color.RED))
);
timeline.setCycleCount(5);
timeline.play();
timeline.setOnFinished(e -> System.out.println("Do something here"));
for(Node circle : root.getChildren()) {
final Circle c = (Circle) circle;
c.fillProperty().bind(colorProperty);
}
}
public static void main(String[] args) {
launch(null);
}
}

I want my JavaFX program to play a video when a button is pressed but only audio plays

I'm new to JavaFX and I need to play a video when a button is pressed, but for some reason I can't quite understand, only the sound is played. Here's my code:
package trailer;
import javafx.event.ActionEvent;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BackgroundImage;
import javafx.scene.layout.VBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class Trailer extends Application implements EventHandler<ActionEvent>{
Button button;
BackgroundImage image;
MediaPlayer player = new MediaPlayer(new Media(getClass().getResource("videonamehere.mp4").toExternalForm()));
MediaView mediaView = new MediaView(player);
public static void main(String[] args){
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception{
primaryStage.setTitle("title content");
button = new Button("button name");
button.setOnAction(this);
Label label = new Label("label content");
label.setTextFill(Color.WHITE);
VBox layout = new VBox();
layout.setPadding(new Insets(200));
layout.setSpacing(20);
layout.getChildren().add(button);
layout.getChildren().add(label);
Scene scene = new Scene(layout, 1920, 1080);
primaryStage.setScene(scene);
scene.getStylesheets().add(Trailer.class.getResource("cssfilename.css").toExternalForm();
primaryStage.show();
}
#Override
public void handle(ActionEvent event){
if(event.getSource() == button){
player.play();
}
}
}
To clarify, the interface with the button, the label, and the CSS effects does show up, but when I press the button only the sound from the video plays.

Create a webview from a button in JavaFX

I have the following simple code where I have an horizontal block where there are two buttons, the remain part is empty. Now, I would like to view a Webview inside the free part after the user press the "current" button. I already did something similar but I wasn't able to manage the layout because it was a Jframe + JavaFX. I thought to re-build totally in JavaFx , for this reason I want to put the webview in a jfxPanel(I think it's the best solution, any other suggest is really appreciate). I should see the webview when I press the button , in this case current, for this reason I create an handle. So, How can I do it?
Thanks in advance
import java.util.ArrayList;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.VPos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Hyperlink;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.TilePane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Launcher extends Application {
public static void main(String[] args) {
launch(Launcher.class, args);
}
Button buttonCurrent;
static HBox web;
static MyBrowser browser_lau;
public void start(Stage stage) {
BorderPane border = new BorderPane();
HBox hbox = addHBox();
border.setTop(hbox);
Scene scene = new Scene(border);
stage.setScene(scene);
stage.setTitle("Layout Sample");
stage.show();
buttonCurrent.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
final JFXPanel jfxPanel = new JFXPanel();
//border.setStyle("-fx-background-color: #ff0000;");
}
});
}
public HBox addHBox() {
HBox hbox = new HBox();
hbox.setPadding(new Insets(15, 12, 15, 12));
hbox.setSpacing(10); // Gap between nodes
hbox.setStyle("-fx-background-color: #336699;");
buttonCurrent = new Button("Current");
buttonCurrent.setPrefSize(100, 20);
Button buttonProjected = new Button("Projected");
buttonProjected.setPrefSize(100, 20);
hbox.getChildren().addAll(buttonCurrent, buttonProjected);
return hbox;
}
}
}
Here is some sample code to get you started, it creates a couple of WebViews and toggles between them depending upon a radio button selection.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class CountThePeople extends Application {
private static final String CURRENT_URL =
"http://www.census.gov/popclock/";
private static final String PROJECTED_URL =
"http://www.sciencedaily.com/releases/2015/08/150810110634.htm";
#Override
public void start(final Stage stage) throws Exception {
WebView current = new WebView();
current.getEngine().load(CURRENT_URL);
WebView projected = new WebView();
projected.getEngine().load(PROJECTED_URL);
StackPane viewHolder = new StackPane();
ToggleGroup choice = new ToggleGroup();
RadioButton currentRadio = new RadioButton("Current");
currentRadio.setToggleGroup(choice);
RadioButton projectedRadio = new RadioButton("Projected");
projectedRadio.setToggleGroup(choice);
choice.selectedToggleProperty().addListener((observable, oldValue, newValue) -> {
if (projectedRadio == newValue) {
viewHolder.getChildren().setAll(projected);
} else {
viewHolder.getChildren().setAll(current);
}
});
choice.selectToggle(currentRadio);
VBox layout = new VBox(10, currentRadio, projectedRadio, viewHolder);
layout.setPadding(new Insets(10));
stage.setTitle("World Population");
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) throws Exception {
launch(args);
}
}

How to show ProgressIndicator in center of Pane in Javafx

I have a Pane with some controls and a button. When I click on the button, I want show ProgressIndicator in center of pane without removing any controls.
When I am adding a ProgressIndicator to pane during onAction of button, it adds it below the button. I want it to overlay on the pane.
The picture below explains what I want.
Code
package fx;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage arg0) throws Exception {
final VBox bx = new VBox();
bx.setAlignment(Pos.CENTER);
TextField userName = new TextField("User Name");
userName.setMaxWidth(200);
TextField email = new TextField("Email");
email.setMaxWidth(200);
Button submit = new Button("Submit");
submit.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
ProgressIndicator pi = new ProgressIndicator();
//adding here but it is adding at below of button
//how to do here
bx.getChildren().add(pi);
//Further process
}
});
bx.getChildren().addAll(userName, email, submit);
Scene c = new Scene(bx);
arg0.setScene(c);
arg0.setMinWidth(500);
arg0.setMinHeight(500);
arg0.show();
}
public static void main(String[] args) {
Main h = new Main();
h.launch(args);
}
}
You need to use a StackPane as your root layout instead of using a VBox. StackPane allows you to stack nodes on top of each other (z-order).
On the button's action you can create a new ProgressIndicator and add it to your StackPane. I have introduced another VBox as the parent to the indicator, because I did not want the indicator to capture all the available space. You can disable the already present VBox to get the greying effect on button's action after the process is done you can enable the VBox again.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TextField;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage arg0) throws Exception {
StackPane root = new StackPane();
VBox bx = new VBox();
bx.setAlignment(Pos.CENTER);
TextField userName = new TextField("User Name");
userName.setMaxWidth(200);
TextField email = new TextField("Email");
email.setMaxWidth(200);
Button submit = new Button("Submit");
submit.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
ProgressIndicator pi = new ProgressIndicator();
VBox box = new VBox(pi);
box.setAlignment(Pos.CENTER);
// Grey Background
bx.setDisable(true);
root.getChildren().add(box);
}
});
bx.getChildren().addAll(userName, email, submit);
root.getChildren().add(bx);
Scene c = new Scene(root);
arg0.setScene(c);
arg0.setMinWidth(500);
arg0.setMinHeight(500);
arg0.show();
}
public static void main(String[] args) {
launch(args);
}
}

Label text position

I have a Label with an image and text
final Label label = new Label(labelText);
label.setTextAlignment(TextAlignment.CENTER);
ImageView livePerformIcon = new ImageView(MainApp.class.getResource("/images/Folder-icon.png").toExternalForm());
label.setGraphic(livePerformIcon);
I get this as a visual result:
How I can change the text position? I want to set the text below the Image?
label.setContentDisplay(ContentDisplay.TOP);
Play with this to see the effect of the different alignment settings:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.text.TextAlignment;
import javafx.stage.Stage;
public class LabelGraphicAlignmentTest extends Application {
#Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
Label label = new Label("Some\ntext");
label.setGraphic(new ImageView(getClass().getResource("/images/Folder-icon.png").toExternalForm()));
label.setMaxWidth(Double.POSITIVE_INFINITY);
label.setMaxHeight(Double.POSITIVE_INFINITY);
label.setStyle("-fx-border-color: blue;");
root.setCenter(label);
ComboBox<ContentDisplay> contentDisplayBox = new ComboBox<>();
contentDisplayBox.getItems().addAll(ContentDisplay.values());
contentDisplayBox.getSelectionModel().select(ContentDisplay.LEFT);
label.contentDisplayProperty().bind(contentDisplayBox.valueProperty());
ComboBox<Pos> alignmentBox = new ComboBox<>();
alignmentBox.getItems().addAll(Pos.values());
alignmentBox.getSelectionModel().select(Pos.CENTER);
label.alignmentProperty().bind(alignmentBox.valueProperty());
ComboBox<TextAlignment> textAlignmentBox = new ComboBox<>();
textAlignmentBox.getItems().addAll(TextAlignment.values());
textAlignmentBox.getSelectionModel().select(TextAlignment.LEFT);
label.textAlignmentProperty().bind(textAlignmentBox.valueProperty());
GridPane ctrls = new GridPane();
ctrls.setHgap(5);
ctrls.setVgap(5);
ctrls.setPadding(new Insets(10));
ctrls.addRow(0, new Label("Content display:"), new Label("Alignment:"), new Label("Text Alignment:"));
ctrls.addRow(1, contentDisplayBox, alignmentBox, textAlignmentBox);
root.setTop(ctrls);
Scene scene = new Scene(root, 600, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I had to center the text of a label which acted like a title. The following code snippet did the trick.
final Label title = new Label("Some text");
title.setMaxWidth(Double.MAX_VALUE);
title.setAlignment(Pos.CENTER);
Good programming :-)
I was able to grab the button from the fxml file:
#FXML Label countDownClockLabel;
Then when the controller was initialized i set the text position:
#FXML
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
countDownClockLabel.setAlignment(Pos.CENTER);
}
You have to import:
import javafx.geometry.Pos;

Resources