javafx label message showing with timer does not work - javafx

So im trying to show a message in javafx on a label and then make it disapear after 1 second. Im able to show the message as desired but i cannot make it dissapear. Actually my problem is that i never appear. So if i use only this:
lbReserva.setText("RESERVA REALITZADA");
Works as expected but obviously it just stay like that. So then i tried this:
try {
lbReserva.setText("RESERVA REALITZADA");
TimeUnit.SECONDS.sleep(1);
lbReserva.setText("");
} catch (InterruptedException e) {
System.err.format("IOException: %s%n", e);
}
But then the label it just never appears. I've tried placing the first set text outside right before the try block. I've tried placing the second set text just after the catch. In any case i got the same result, the label never appears, or probably appears and straight away dissapear. Any clues what im doing wrong? thank you so much in advance.
pd: i have tried using Thread.sleep instead of TimeUnit but i got the same result.

Use PauseTransition.
import javafx.animation.PauseTransition;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class TestingGround extends Application
{
#Override
public void start(Stage stage) throws Exception
{
Label label = new Label("Hello World!");
PauseTransition wait = new PauseTransition(Duration.seconds(1));
wait.setOnFinished((e) -> {
label.setVisible(false);
});
wait.play();
VBox root = new VBox(label);
stage.setScene(new Scene(root, 700, 500));
stage.show();
}
public static void main(String[] args)
{
launch(args);
}
}

Related

Popup with ScrollPane makes main Stage TextField unresponsive to key events like LEFT, RIGHT, HOME, END

I want to create a Popup for main Stage TextField. Popup contains ScrollPane which holds possible options as Buttons.
After Popup shown TextField key events like left, rigth, home, end have no effect. Key events are received on TextField.
Is there any reasonable solution or workaround for this issue.
To reproduce please type in some text and try to press left arrow.
import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Popup;
import javafx.stage.Stage;
public class PopupApp extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
TextField textField = new TextField();
StackPane stackPane = new StackPane(textField);
stage.setScene(new Scene(stackPane));
stage.show();
ScrollPane scrollPane = new ScrollPane(new VBox(new Button("Option1"), new Button("Option2")));
Popup popup = new Popup();
popup.getContent().add(scrollPane);
Point2D pinPoint = textField.localToScreen(0., textField.getHeight());
popup.show(textField, pinPoint.getX(), pinPoint.getY());
textField.addEventHandler(KeyEvent.KEY_RELEASED, event -> {
System.out.println("KEY_RELEASED " + event);
});
textField.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
System.out.println("KEY_PRESSED " + event);
});
}
}
Actually, the KEY_PRESSED event is not being received by your textField when pressing Keys like Left, Right, ... This is shown by the output from your program.
You are facing this problem because Events are being redirected to Popup. If these events are consumed while dispatching, then the effect of these events are not shown by textField. In your case it is due to the presence of Button on Popup. (Most likely due to the presence of node that can receive focus. Not sure though). To solve this you can set your own EventDispatcher. Something like this before popup.show():
popup.setEventDispatcher((event, tail) -> {
if (event.getEventType() != RedirectedEvent.REDIRECTED) {
tail.dispatchEvent(event);
}
return null;
});
All the redirected events into the Popup will now be discarded and further dispatching does not occur. You can tweak this to suit your requirement.

JavaFX Slider : How to drag the thumb only by increments

I am trying to implement the Slider such that user can drag only by given increments. I tried in different ways by using the Slider API, but didnt get the desired results. Below is a quick demo of what I had tried. I am expecting to drag the thumb only in increments of 10 not with intermediate values. snapToTicks is doing what I required, but only after finishing the drag. I am trying to not move the thumb till the next desired block increment is reached.
Can anyone let me know how can i achieve this. Below is the screenshot while dragging.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class SliderDemo extends Application {
public static void main(String... args){
Application.launch(args);
}
#Override
public void start(Stage stage) throws Exception {
Label label = new Label();
label.setStyle("-fx-font-size:30px");
Slider slider = new Slider(5,240,5);
slider.setBlockIncrement(10);
slider.setMajorTickUnit(10);
slider.setMinorTickCount(0);
slider.setShowTickLabels(true);
slider.setShowTickMarks(true);
slider.setSnapToTicks(true);
slider.valueProperty().addListener((obs,old,val)->label.setText((int)Math.round(val.doubleValue())+""));
VBox root = new VBox(slider,label);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(20));
root.setSpacing(20);
Scene scene = new Scene(root,600,200);
stage.setScene(scene);
stage.show();
}
}
The solution is to set the value of the slider directly inside of the listener. The listener will not be called again
final ChangeListener<Number> numberChangeListener = (obs, old, val) -> {
final double roundedValue = Math.floor(val.doubleValue() / 10.0) * 10.0;
slider.valueProperty().set(roundedValue);
label.setText(Double.toString(roundedValue));
};
slider.valueProperty().addListener(numberChangeListener);
If you use Math.floor() instead of round you get a more intuatuive behavior of the thumb.

Java9 bug in javafx PieChart labels

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class Main extends Application {
#Override
public void start(Stage stage) {
try {
Scene pie;
Scene begin;
//pie scene
ObservableList<PieChart.Data> pieChartData=FXCollections.observableArrayList();
PieChart pieChart = new PieChart(pieChartData);
Button btBack = new Button("Back");
pieChart.setTitle("Test");
VBox container = new VBox(20);
container.getChildren().addAll(pieChart,btBack);
container.setAlignment(Pos.CENTER);
BorderPane pane = new BorderPane();
pane.setCenter(container);
pie =new Scene(pane,800,600);
//begin scene
VBox container2 = new VBox(20);
Button btPie = new Button("pie");
container2.getChildren().add(btPie);
BorderPane pane2 = new BorderPane();
container2.setAlignment(Pos.CENTER);
pane2.setCenter(container2);
begin=new Scene(pane2,50,50);
//handler
btPie.setOnAction(e->{
pieChartData.clear();
for(int i=0;i<5;++i)
pieChartData.add(new PieChart.Data(""+i, i));
stage.setScene(pie);
});
btBack.setOnAction(e->stage.setScene(begin));
stage.setScene(begin);
stage.show();
} catch (Exception e) {
e.printStackTrace(); // exception handling: print the error message on the console
}
}
public static void main(String[] args) {
launch(args);
}
}
With the above code, it first shows the stage with a button "pie". Clicking the button shows a pie chart with a button "back". The back button is used to go back to the initial screen.
The problem in this code is that after showing the pie chart for the second time, the pie chart's labels suddenly become crammed.
It can be seen with
1. click pie
2. click back
3. click pie -> problem shown
I can see that there is a problem, but I can't really see the reason. Furthermore, this problem only arise in java9; it works well in java8.
Can anyone find me the reason please?
The suggestion by JKostikiadis in the comment:
... you can fix the bug by adding container.layout(); after the for loop and before the stage.setScene(pie); in order to force the VBox to layout its children
helped me.

How can I remove my javafx program from the taskbar

I need remove my javafx app from the taskbar. I tried StageStyle.UTILITY. This is works but I need both UNDECORATED and UTILITY stage styles or another solvings.
Thank you for your replies.
Sorry you've been waiting so long for some sort of an answer on this, the following is mainly for people who come to this in the future hoping to discover a way of achieving this.
Let me start of by saying I wouldn't consider the following a solution but more of a workaround.
Assigning more than one initStyle to a stage is not possible however hiding the application from the task-bar and assigning an initStyle other than utility to the stage that is shown is.
To achieve this one must create two stages, the stage they want the user to see, and an another stage that will be considered the parent of the main stage and will be of initStyle.UTILITY this will prevent the icon from showing in the task-bar.
Below you can see the hello world example from oracles documentation modified to allow for an undecorated window with no icon (Note if one wanted to achieve a transparent/decorated window they could do so by changing the style of mainStage).
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class MultipleStageStyles extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.initStyle(StageStyle.UTILITY);
primaryStage.setOpacity(0);
primaryStage.setHeight(0);
primaryStage.setWidth(0);
primaryStage.show();
Stage mainStage = new Stage();
mainStage.initOwner(primaryStage);
mainStage.initStyle(StageStyle.UNDECORATED);
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
mainStage.setScene(new Scene(root, 300, 250));
mainStage.show();
}
}

How to remove selection on input in editable ComboBox

Yes, there are earlier threads and guides on the issue. And they tell me that either setValue(null) or getSelectionModel().clearSelection() should be the answer. But doing any of these gives me a java.lang.IndexOutOfBoundsException.
What I want to do is to clear the selection everytime something is being written into the combo box. This is because it causes problems and looks weird when you write something in the combo box and something else remains selected in the combo box popup.
Here's an SSCCE:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.converter.IntegerStringConverter;
public class SSCCE extends Application {
#Override
public void start(Stage stage) {
HBox root = new HBox();
ComboBox<Integer> cb = new ComboBox<Integer>();
cb.setEditable(true);
cb.getItems().addAll(1, 2, 6, 7, 9);
cb.setConverter(new IntegerStringConverter());
cb.getEditor().textProperty()
.addListener((obs, oldValue, newValue) -> {
// Using any of these will give me a IndexOutOfBoundsException
// Using any of these will give me a IndexOutOfBoundsException
//cb.setValue(null);
//cb.getSelectionModel().clearSelection();
});
root.getChildren().addAll(cb);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
You are running into this JavaFX ComboBox change value causes IndexOutOfBoundsException issue, which is causing the IndexOutOfBoundsException. These are kind of a pain.
There is a bit of a logical issue with your attempts anyway: clearing the selected value will cause the editor to update its text, so even if this worked it would make it impossible for the user to type. So you want to check that the changed value isn't the one typed in. This seems to fix both issues:
cb.getEditor().textProperty()
.addListener((obs, oldValue, newValue) -> {
if (cb.getValue() != null && ! cb.getValue().toString().equals(newValue)) {
cb.getSelectionModel().clearSelection();
}
});
You may need to change the toString() call, depending on the exact converter you are using. In this case, it will work.

Resources