JAVAFX - How to make a textfield active on event action - javafx

GridPane layout = new GridPane();
Label wordInstruction = new Label("Word");
TextField wordField = new TextField();
Label translationInstruction = new Label("Translation");
TextField translationField = new TextField();
Label error = new Label();
layout.setVgap(10);
layout.setHgap(10);
layout.setPadding(new Insets(10, 10, 10, 10));
layout.setAlignment(Pos.CENTER);
Button addButton = new Button("Add");
// Stops the button from consuming mouse events and allows it to become the default button.
addButton.setSkin(new ButtonSkin(addButton) {
{
this.consumeMouseEvents(false);
}
});
// The button can now be pressed with the enter key.
addButton.setDefaultButton(true);
layout.add(wordInstruction, 0, 0);
layout.add(wordField, 0, 1);
layout.add(translationInstruction, 0, 2);
layout.add(translationField, 0, 3);
layout.add(addButton, 0, 4);
layout.add(error, 0, 6);
addButton.setOnAction((event) -> {
String word = wordField.getText();
String translation = translationField.getText();
if (!translationField.getText().isEmpty()) {
this.dictionary.add(word.toLowerCase(), translation.toLowerCase());
error.setText("");
wordField.clear();
} else {
error.setText("Please input a translation.");
}
translationField.clear();
});
return layout;
}
Hello, I've just started using JavaFX and I've not been able to find anything in the documentation related to my problem. When I press the addButton, I want the user to be able to write into the wordField textField straight away instead of having to click it or tab all the way to it. Is there any way to make the textField active in my addButton.setOnAction function?
Thank you in advance.

How about running the TextField.requestFocus() method?

Related

How to bind TextField and ProgressBar in JavaFx

I'm trying to Use reactive bindings to bind the value of alcoholPercentageField to the progress property of alcoholBar.
The progress bar will "full" when alcoholic content is set to 20 % and empty when the alcoholic content is 0
My Code-
public void start(Stage stage) throws Exception {
stage.setTitle("Mead calculator");
// Creating the fields and components
TextField waterAmountField = new TextField();
TextField alcoholPercentageField = new TextField();
TextField sugarAmountField = new TextField();
Label meadTotalAmount = new Label();
Label assessmentLabel = new Label("");
//assessmentLabel.textProperty().bind(alcoholPercentageField.textProperty());
//Conditional Binding Error
assessmentLabel.textProperty().bind(Bindings.when((alcoholPercentageField.textProperty().lessThan(5))).then("Smart").otherwise("Bad"));
ProgressBar alcoholBar = new ProgressBar();
//Error is here
alcoholBar.progressProperty().bind(alcoholPercentageField.textProperty() * 5);
Rest of the Code: some visual things
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(25, 25, 25, 25));
var columnOneConstraints = new ColumnConstraints(150, 150, Double.MAX_VALUE);
columnOneConstraints.setHalignment(HPos.RIGHT);
var columnTwoConstrains = new ColumnConstraints(200,200, Double.MAX_VALUE);
columnTwoConstrains.setHgrow(Priority.SOMETIMES);
grid.getColumnConstraints().addAll(columnOneConstraints, columnTwoConstrains);
alcoholBar.setMaxWidth(Double.MAX_VALUE);
GridPane.setColumnSpan(alcoholBar, 2);
GridPane.setHalignment(assessmentLabel, HPos.RIGHT);
sugarAmountField.setDisable(true);
grid.add(new Label("Water (l):"), 0, 0);
grid.add(waterAmountField, 1, 0);
grid.add(new Label("Vol-%:"), 0, 1);
grid.add(alcoholPercentageField, 1, 1);
grid.add(new Label("Sugar (kg):"), 0, 2);
grid.add(sugarAmountField, 1, 2);
grid.add(new Label("Lemons: "), 0, 3);
grid.add(new Label("To taste"), 1, 3);
grid.add(new Label("Mead total (kg):"), 0, 4);
grid.add(meadTotalAmount, 1, 4);
grid.add(alcoholBar, 0, 5);
grid.add(assessmentLabel, 1, 6);
// Okay, layout creation stops here
// And of course set the scene and show the stage as always
stage.setScene(new Scene(grid, 500, 400));
stage.show();
}
}
You need to create some additional Property and Binding objects.
First, create properties for your TextField alcoholPercentageField. Then, you'll bind them using a StringConverter to convert the text entered into doubles.
Finally, use bindBidirectional to propagate and lastly bind it with progressBar by dividing 20 ( The progress bar will be "full" when alcoholic content is set to 20 %)
Code Will be like this-
// Properties used for bindings
DoubleProperty alcoholPercent = new SimpleDoubleProperty();
//Setup the converters to get the input from the textfields
StringConverter<? extends Number> converter = new DoubleStringConverter();
Bindings.bindBidirectional(alcoholPercentageField.textProperty(), alcoholPercent, (StringConverter<Number>) converter);
alcoholBar.progressProperty().bind(alcoholPercent.divide(20));
For Conditional Binding, check this Conditional Binding
Code would be like this-
assessmentLabel.textProperty().bind(Bindings.when(alcoholPercent.lessThan(5)).then("Smart").otherwise("Bad"));
assessmentLabel.textFillProperty().bind(Bindings.when(alcoholPercent.lessThan(5)).then(Color.GREEN).otherwise(Color.RED));
Use the Bindings API.
Note that the progress is supposed to be between 0 and 1, so if you are entering percentages, instead of proportions, into your text field you need to divide by 100:
alcoholBar.progressProperty().bind(Bindings.createDoubleBinding(
() -> 0.05 * Double.parseDouble(alcoholPercentageField.getText()),
alcoholPercentageField.textProperty()
));
You might want to implement more complex logic to, e.g. check for a valid number, or at least non-empty text field.

JavaFX custom dialog set Layout of node

We created a Custom Dialog without an FXML file. We are using JavaFX 8.
The dialog loads and functions as expected but we can not move the Buttons and the TextField to enhance the styling.
We have tried to use tf.setLayoutY(50) this has no effect.
We used this tf.setPromptText("This Works ?") and it works.
We would rather not use css to accomplish this styling.
And we will consider a FXML file if we can keep the two event handlers that force data to be entered in the TextField.
So the question is: How to style this Custom Dialog?
The code is a mess as it includes some concepts we tried:
public void CustomDialog() {
Dialog dialog = new Dialog<>();
dialog.setResizable(false);
final Window window = dialog.getDialogPane().getScene().getWindow();
stage = (Stage) window;
stage.setMinHeight(600);
stage.setMinWidth(400);
TextField tf = new TextField();
tf.setLayoutX(10);
tf.setLayoutY(50);
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
dialog.getDialogPane().getChildren().add(tf);
dialog.getDialogPane().setContent(tf);
// Create an event filter that consumes the action if the text is empty
EventHandler<ActionEvent> filter = event -> {
if (tf.getText().isEmpty()) {
event.consume();
}
};
// lookup the buttons
ButtonBase okButton = (Button) dialog.getDialogPane().lookupButton(ButtonType.OK);
Button cancelButton = (Button) dialog.getDialogPane().lookupButton(ButtonType.CANCEL);
// add the event-filter
okButton.addEventFilter(ActionEvent.ACTION, filter);
cancelButton.addEventFilter(ActionEvent.ACTION, filter);
stage.setOnCloseRequest(event -> {
if (tf.getText().isEmpty()) {
event.consume();
}
}
//Scene scene = new Scene(root);
//dialogStage.setScene(scene);
dialog.initModality(Modality.APPLICATION_MODAL);
//dialogStage.setAlwaysOnTop(true);
//dialogStage.setResizable(false);
tf.setPromptText("This Works ?");
tf.requestFocus();// This does not work
dialog.showAndWait();
}
Grendel we enhanced your answer so anyone who comes by and sees the code you posted in your question will understand as you said it was a mess
Your posted answer was real old school but less work perhaps than building a FXML file
Besides it is good to know some old school tricks
public void NewDialog(){
Label lblAmt = new Label("Enter Amount");
Button btnOK = new Button("OK");
TextField txtAmt = new TextField();
AnchorPane secondaryLayout = new AnchorPane();
secondaryLayout.setStyle("-fx-border-color:red;-fx-border-width:10px; -fx-background-color: lightblue;");
secondaryLayout.getChildren().addAll(lblAmt,btnOK,txtAmt);
lblAmt.setLayoutX(30);
lblAmt.setLayoutY(30);
txtAmt.setLayoutX(164);
txtAmt.setLayoutY(25);
txtAmt.setMaxWidth(116);
btnOK.setLayoutX(190);
btnOK.setLayoutY(100);
btnOK.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");
lblAmt.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");
txtAmt.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");
Scene secondScene = new Scene(secondaryLayout, 300, 180);
EventHandler<ActionEvent> filter = event -> {
if(txtAmt.getText().isEmpty()) {
event.consume();
}
};
// New window (Stage)
Stage newWindow = new Stage();
newWindow.initStyle(StageStyle.UNDECORATED);
//newWindow.initModality(Modality.APPLICATION_MODAL);
newWindow.setResizable(false);
newWindow.setTitle("Second Stage");
newWindow.setScene(secondScene);
btnOK.addEventHandler(ActionEvent.ACTION,filter);
btnOK.setOnAction(evt -> {
String str = txtAmt.getText();
System.out.println("################ str "+str);
if(txtAmt.getText().equals("")) {
evt.consume();
txtAmt.requestFocus();
}else{
newWindow.close();
}
});
newWindow.setOnCloseRequest(event -> {
if(txtAmt.getText().isEmpty()) {
event.consume();
}
});
txtAmt.requestFocus();
newWindow.showAndWait();
}

Adding label into border, JavaFX

When I'm trying to add label into the gridpane as the second picture shows, it's not working. I have tried many things like adding CSS and it's still not working. Why are lines 113 and 114 not working?
(opcje.setStyle("-fx-background-color: #f4f4f4");)
Here is what I have:
Here is what I need:
My code:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
public class KCK_lab1_zad2 extends Application {
#SuppressWarnings("static-access")
public void start (Stage primaryStage) {
try {
primaryStage.setTitle("Narzedzie przetwarzania plikow");
BorderPane glownyBorderPane = new BorderPane();
Scene scene = new Scene(glownyBorderPane, 600, 200);
GridPane lewyGridPane = new GridPane();
GridPane prawyGridPane = new GridPane();
glownyBorderPane.setLeft(lewyGridPane);
glownyBorderPane.setRight(prawyGridPane);
glownyBorderPane.setMargin(lewyGridPane, new Insets(0, 15, 0, 0));
Label zrodlo = new Label("Źrodlo");
Label wynik = new Label("Wynik");
TextField text1 = new TextField();
TextField text2 = new TextField();
Button przegladaj1 = new Button("Przegladaj...");
Button przegladaj2 = new Button("Przegladaj...");
lewyGridPane.setVgap(15);
lewyGridPane.setHgap(0);
lewyGridPane.setPadding(new Insets(15));
lewyGridPane.setLayoutX(100);
lewyGridPane.setLayoutY(100);
lewyGridPane.setMinSize(100, 150);
text1.setPrefSize(100, 20);
text2.setPrefSize(100, 20);
przegladaj1.setPrefSize(100, 20);
przegladaj2.setPrefSize(100, 20);
glownyBorderPane.setPadding(new Insets(20, 10, 10, 10));
Label panelPlikow = new Label("Panel plików");
panelPlikow.getStyleClass().add("title");
panelPlikow.setPadding(new Insets(-60, -20, 0, 0));
panelPlikow.setPrefWidth(150);
lewyGridPane.add(panelPlikow, 0, 0);
lewyGridPane.add(zrodlo, 0, 0);
lewyGridPane.add(text1, 1, 0);
lewyGridPane.add(przegladaj1, 2, 0);
lewyGridPane.add(wynik, 0, 1);
lewyGridPane.add(text2, 1, 1);
lewyGridPane.add(przegladaj2, 2, 1);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//grd.prefHeightProperty().bind(root.heightProperty());
//glownyBorderPane.borderProperty();
lewyGridPane .setStyle("-fx-border-style: solid inside;");
lewyGridPane .setStyle("-fx-border-width: 1;");
lewyGridPane .setStyle("-fx-border-insets: 1;");
lewyGridPane .setStyle("-fx-border-radius: 1;");
lewyGridPane .setStyle("-fx-border-color: black;");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Label opcje = new Label ("Opcje uruchomienia");
Button uruchom = new Button ("Uruchom przetwarza...");
Button pomoc = new Button ("Pomoc");
Button o_programie = new Button ("O programie");
Button zakoncz = new Button ("Zapisz i zakończ");
prawyGridPane.setVgap(0);
prawyGridPane.setHgap(0);
prawyGridPane.setPrefSize(150, 200);
prawyGridPane.setMaxWidth(150);
prawyGridPane.setPadding(new Insets(15));
prawyGridPane.setPrefSize(400, 300);
opcje.setPrefSize(150, 20);
uruchom.setPrefSize(150, 20);
o_programie.setPrefSize(150, 20);
zakoncz.setPrefSize(150, 20);
opcje.getStyleClass().add("title");
opcje.setPadding(new Insets(-34, -20, 0, 0));
VBox vbox = new VBox();
prawyGridPane.add(vbox, 0, 0);
opcje.setPrefWidth(150);
opcje.setStyle("-fx-background-color: #f4f4f4");
panelPlikow.setStyle("-fx-background-color: #f4f4f4");
vbox.getChildren().add(opcje);
vbox.getChildren().add(uruchom);
vbox.getChildren().add(pomoc);
vbox.getChildren().add(o_programie);
vbox.getChildren().add(zakoncz);
vbox.toBack();
//opcje.toFront();
uruchom.prefWidthProperty().bind(glownyBorderPane.widthProperty());
pomoc.prefWidthProperty().bind(glownyBorderPane.widthProperty());
o_programie.prefWidthProperty().bind(glownyBorderPane.widthProperty());
zakoncz.prefWidthProperty().bind(glownyBorderPane.widthProperty());
uruchom.prefHeightProperty().bind(glownyBorderPane.heightProperty());
pomoc.prefHeightProperty().bind(glownyBorderPane.heightProperty());
o_programie.prefHeightProperty().bind(glownyBorderPane.heightProperty());
zakoncz.prefHeightProperty().bind(glownyBorderPane.heightProperty());
/*
opcje .setStyle("-fx-font: 28px Vivaldi;");
opcje .setStyle("-fx-font-color: red;");
opcje .setStyle("-fx-background-color: white;");
opcje .setStyle("-fx-translate-y: -16;");
opcje .setStyle("-fx-content-display: top;");
opcje .setStyle("-fx-background-color: black;");
opcje.setTextFill(Color.RED);
opcje.setStyle("-fx-background-color: white");
*/
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//grd.prefHeightProperty().bind(root.heightProperty());
//glownyBorderPane.borderProperty();
prawyGridPane .setStyle("-fx-border-style: solid inside;");
prawyGridPane .setStyle("-fx-border-width: 1;");
prawyGridPane .setStyle("-fx-border-insets: 1;");
prawyGridPane .setStyle("-fx-border-radius: 1;");
prawyGridPane .setStyle("-fx-border-color: black;");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
primaryStage.setScene(scene);
primaryStage.setMinHeight(250);
primaryStage.setMinWidth(580);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]){
launch(args);
}
}
The problem is the padding of the title-labels. To recognize this, set the background-colors of the title-labels, e.g. to green, set the padding to 0 and increase it step by step towards your value. If you do that, the text shifts up (what is desired), but the content (and thus the background) becomes smaller and finally disappears (what you did not intend). Overall, it does not work right with padding:
If you really want to keep your solution you can compensate for the problem by using the graphic-property of the label usually applied to add an icon to the label.
Replace
Label panelPlikow = new Label("Panel plików");
with
Label panelPlikow = new Label();
panelPlikow.setGraphic(new Label(" Panel plików "));
panelPlikow.getGraphic().setStyle("-fx-background-color: #f4f4f4;");
and analogously for the other button. That results in:
However, I don't know if it works in combination with your title-styleclass since you haven't post it. You have to try that.
I would like to point out that there are conceptually better ways to achieve what you want!
One possibility that comes close to your solution is, not to add the GridPane directly to the BorderPane, but a Pane, with the Pane containing the GridPane and the label. Here, the label can be positioned freely without a padding.
Another possibility is to use the Borders-control from ControlsFX (http://fxexperience.com/controlsfx/features/). It does exactly what you want, i.e. it surrounds an arbitrary control with a border and you can optionally define a title.
GridPane lewyGridPane = new GridPane();
Node leftWithBorder = Borders.wrap(lewyGridPane).lineBorder().title("Panel plików").color(Color.BLACK).buildAll();
GridPane prawyGridPane = new GridPane();
Node rightWithBorder = Borders.wrap(prawyGridPane).lineBorder().title("Opcje uruchomienia").color(Color.BLACK).buildAll();
glownyBorderPane.setLeft(leftWithBorder);
glownyBorderPane.setRight(rightWithBorder);
Of course, you have to remove the currently existing GridPane-borders and title-labels and you have to adapt margins, paddings, preferred sizes etc. Moreover you have to download and add the controlsfx-jar to the build path.
With the ControlsFX-Borders-control the GUI looks almost identical:

JavaFX BorderPane will not take on background colour

I'm trying to teach myself basic JavaFX by following the tutorials provided by Oracle.
In the BorderPane tutorial (https://docs.oracle.com/javafx/2/layout/builtin_layouts.htm) it specifies a background colour.
This is a snippet of my code:
/**
* This Method creates and defines a horizontal box with a button.
*/
public HBox addHorizontalBoxWithButton() {
// set up horizontal box and button
HBox hBox = new HBox();
hBox.setPadding(new Insets(10, 10, 10, 10));
hBox.setSpacing(10);
hBox.setStyle("-fx-background-colour: #FFFFFF;");
hBox.setAlignment(Pos.CENTER);
Button startButton = new Button("CLICK ME");
startButton.setPrefSize(100, 30);
// set up a message
Text message = new Text("Click the button to get started.");
message.setId("message");
hBox.getChildren().add(message);
hBox.getChildren().add(startButton);
return hBox;
}
I have tried various different background colours, none of which work. Am I missing something here?
Also, I am using a .css file but it only adds style to the 'message'.
The only problem with the original code is that you have a "typo" (anglification?) in your style setting. It should be
hBox.setStyle("-fx-background-color: #FFFFFF;");
not
hBox.setStyle("-fx-background-colour: #FFFFFF;");
Using an external style sheet with
#hbox {
-fx-background-color: red ;
}
is a better solution than using inline styles.
Okay I just solved this.
I changed my code like so:
/**
* This Method creates and defines a horizontal box with a button.
*/
public HBox addHorizontalBoxWithButton() {
// set up horizontal box and button
HBox hBox = new HBox();
hBox.setId("hBox");
hBox.setPadding(new Insets(10, 10, 10, 10));
hBox.setSpacing(10);
// hBox.setStyle("-fx-background-colour: #FFFFFF;");
hBox.setAlignment(Pos.CENTER);
Button startButton = new Button("CLICK ME");
startButton.setPrefSize(100, 30);
// set up a message
Text message = new Text("Click the button to get started.");
message.setId("message");
hBox.getChildren().add(message);
hBox.getChildren().add(startButton);
return hBox;
}
And I added this to the .css file:
#hBox {
-fx-background-color: linear-gradient(#04B45F, #81F79F);
}

Change label javafx on keyboard input

I would like a javafx label to be automatically updated to what is being typed into a textfield, currently i have it changing only when enter is clicked. I am using a mix of swing and javafx.
is this possible?
thanks
exprField.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Platform.runLater(new Runnable() {
#Override
public void run() {
fxLabel.setText(exprField.getText());
}
});
}
});
You can use the Binding-Mechanism for this purpose.
GridPane p = new GridPane();
TextField tf = new TextField("DEFAULT");
Label l1 = new Label("...");
l1.textProperty().bind(tf.textProperty());
p.add(tf, 0, 0);
p.add(l1, 1, 0);
Scene sc = new Scene(p, 500, 500);
arg0.setScene(sc);
arg0.show();
This code sets a textbox and a label into a gridpane. The text property of the label is bound to the text property of the textfield, which means as soon as the textfields changes, the text of the label gets updated according to whatever text is now in the textfield.
More information can be found here: http://docs.oracle.com/javafx/2/binding/jfxpub-binding.htm

Resources