I am making a simulator in which I have a button with different behavior depending on the duration of the press.
If the button is pressed less than 3 seconds, prints nothing, between 3 and 10, prints 1 and higher than 10 prints 2.
Should I try with MouseListener or ActionListener? Any example code would be great! Thanks.
Listen to changes in the pressed property:
public class StageTest extends Application{
private long startTime;
#Override
public void start(Stage primaryStage) {
Button btn = new Button("Hold");
Label label= new Label();
btn.pressedProperty().addListener((obs, wPressed, pressed) -> {
if (pressed) {
startTime = System.nanoTime();
label.setText("");
} else {
label.setText("Button was pressed for "+ (System.nanoTime() - startTime) + " nanos");
}
});
Pane root = new VBox(btn, label);
Scene scene = new Scene(root, 300, 100);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch();
}
}
A simple hack:
Create a timer and start the timer as soon as the button is pressed. Set the interval of the timer to one second then have a counter that increments each time the timer event is fired to keep track of how many seconds it was pressed. As soon as the button is released stop the timer and perform any action you want to
Related
Recently, I have been learning Java and now I have encountered JavaFX. My question is, how do I update/change Text by clicking on a Button?`
public class Main extends Application {
Scene start;
int counter = 0;
#Override
public void start(Stage primaryStage) throws Exception{
BorderPane startLayout = new BorderPane();
Button testButton = new Button("+1");
testButton.setOnAction(event -> {
counter++;
System.out.println("counter: " + counter);
});
Text test = new Text("Counter: " + counter);
test.setFont(Font.font("Consolas", 25));
test.setFill(Color.CORNFLOWERBLUE);
startLayout.setTop(test);
startLayout.setCenter(testButton);
start = new Scene(startLayout, 1280, 720);
primaryStage.setTitle("Test");
primaryStage.setScene(start);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
What happens here is that I get the Text in the top-left corner and the Button in the middle of the screen. The Text shows "Counter: 0". When I press the Button I want the text to show "Counter: 1" or "Counter: 2"... depending on how many times I press the Button but when I press it, nothing happens, the counter stays at 0 in the window. What am I doing wrong? or, is there any other way to do it?
Have you tried with test.setText("Counter" + counter); in the event of the button?
I need to know - how much time the mouse was delayed over the component in stationary. I mean how long did it stay completely stationary over a node. I did not find the standard method. Thank you.
Simply use the onMouseMoved handler to do this; You just need to save the time and calculate the difference:
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
root.setOnMouseMoved(new EventHandler<MouseEvent>() {
long lastTriggered = System.currentTimeMillis();
#Override
public void handle(MouseEvent event) {
long t = System.currentTimeMillis();
System.out.println("last moved " + (t - lastTriggered) + "ms ago");
lastTriggered = t;
}
});
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
You may want to listen for the stage containing the node beinc closed/iconified in addition to that...
I am building an alarm and it consists of two parts
an animated button created in javafx class and the engine which is created normally
what I need is whenever user press the animated button that closes the button and fire up the engine then after the engine is closed there will be some time then animated button appears again and so on
so I used ::
notify_me.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
new engine();
Platform.exit();
}
});
and in order to repeat this process I used
Timer t = new Timer(0,new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
while(true){
javafx.launch(javafx.class);
//some extra code goes here including sleep for
//some time and check for engine window state
}
}
});
t.start();
but I am facing two problems:
some extra code isn`t implemented until platform is exited,
launch() cannot be called more than once
so how can I achieve that without using threads ?? thanks
You probably won't get around using Threads. I'd recommend not shutting down the fx application thread however. Just close all windows and show (some of) them again after the delay:
#Override
public void start(Stage primaryStage) {
Button btn = new Button("Hide me 5 sec");
// prevent automatic exit of application when last window is closed
Platform.setImplicitExit(false);
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
// timer should be a daemon (-> not prevent jvm shutdown)
Timer timer = new Timer(true);
btn.setOnAction((ActionEvent event) -> {
timer.schedule(new TimerTask() {
#Override
public void run() {
// make window reappear (needs to happen on the application thread)
Platform.runLater(primaryStage::show);
}
}, 5000l);
// hide window
primaryStage.close();
});
// allow exiting the application by clicking the X
primaryStage.setOnCloseRequest(evt -> Platform.exit());
primaryStage.show();
}
Im writing a small program that involves a timer but for some reason I cant get the TimerTask to update the value of my Label.setText
public class Main extends Application {
Label TimerLabel;
/* Create a Button named button */
Button button;
/* Create three Radiobuttons named Radio1,Radio2,Radio3 */
RadioButton Radio1, Radio2, Radio3;
Timer QuestionTimer = new Timer();
TimerTask QuestionTick = new TimerTask() {
#Override
public void run() {
TimerLabel.setText(String.valueOf(Integer.valueOf(TimerLabel.getText())+1));
}
};
public static void main(String[] args) {
launch(args);
}
/*UI Part*/
#Override
public void start(Stage primaryStage) throws Exception {
/*Window(Stage) Title is set to "Try 1"*/
primaryStage.setTitle("Try 1");
/*Button properties*/
button = new Button();
button.setText("Click Me");
//Radio Button
Radio1 = new RadioButton();
Radio1.setText("Click Me 1");
Radio1.setOnAction(e->{
System.out.println("Radio Button Clicked");
});
Radio2 = new RadioButton();
Radio2.setText("Click Me 2");
Radio2.setOnAction(e->{
System.out.println("Radio Button 2 Clicked");
});
Radio3 = new RadioButton();
Radio3.setText("Click Me 3");
Radio3.setOnAction(e->{
System.out.println("Radio Button 3 Clicked");
});
TimerLabel = new Label();
TimerLabel.setText("0");
/*Here my layout is defined */
Pane Buttonlayout = new Pane();
button.setLayoutX(200);
button.setLayoutY(200);
Radio1.setLayoutX(15);
Radio1.setLayoutY(20);
Radio2.setLayoutX(15);
Radio2.setLayoutY(40);
Radio3.setLayoutX(15);
Radio3.setLayoutY(60);
TimerLabel.setLayoutX(100);
TimerLabel.setLayoutY(20);
Buttonlayout.getChildren().add(button);
Buttonlayout.getChildren().add(Radio1);
Buttonlayout.getChildren().add(Radio2);
Buttonlayout.getChildren().add(Radio3);
Buttonlayout.getChildren().add(TimerLabel);
/*Here we define the scene (aka everything inside the stage (inside the window))*/
Scene scene1 = new Scene(Buttonlayout,300,250);
primaryStage.setScene(scene1);
primaryStage.show();
QuestionTimer.scheduleAtFixedRate(QuestionTick,1000,1000);
}
}
So thats my code, I know most of it seems stupid but I first wanted to start programming on the timer and well it didnt work. Any kind of help would be appreciated
From the code it appears you are utilizing the java.util.Timer class. The documentation states Implementation note: All constructors start a timer thread. The the JavaFX UI should not be updated from another thread, which is what you are doing with the timer.
Rather than updating the UI directly use the Platform.runLater(Runnable) to schedule the UI tasks on the main JavaFX thread.
javafx.application.Platform.runLater(new Runnable() {
#Override
public void run() {
TimerLabel.setText(String.valueOf(Integer.valueOf(TimerLabel.getText())+1));
}
}
And please, do yourself a favor and get rid of the method chaining. It will make it easier to debug when Integer.valueOf throws an Exception.
String timer_label = TimerLabel.getText();
Integer timer_int = Integer.valueOf(timer_label);
String timer_text = String.valueOf(timer_int + 1);
TimerLabel.setText(timer_text);
I have coded a simple countdown timer in JavaFX and implements the Timer with binding so whenever the value of timeSeconds changes, the timerLabel text also changes.
How to get the value of current seconds and show it to console window?
the output should display the value of current seconds every new line like:
5
4
3
2
1
0
public class FXTimerBinding extends Application
{
// private class constant and somme variables
private static final Integer STARTTIME = 5;
private Timeline timeline;
private Label timerLabel = new Label();
private IntegerProperty timeSeconds = new SimpleIntegerProperty(STARTTIME);
#Override
public void start(Stage primaryStage)
{
// setup the Stage and the Scene(the scene graph)
primaryStage.setTitle("FX Timer binding");
Group root = new Group();
Scene scene = new Scene(root, 300, 250);
// configure the label
timerLabel.setText(timeSeconds.toString());
timerLabel.setTextFill(Color.RED);
timerLabel.setStyle("-fx-font-size: 4em;");
// Bind the timerLabel text property to the timeSeconds property
timerLabel.textProperty().bind(timeSeconds.asString());
// create and configure the Button
Button button = new Button("Start timer");
button.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent event)
{
if(timeline != null)
timeline.stop();
timeSeconds.set(STARTTIME);
timeline = new Timeline();
KeyValue keyValue = new KeyValue(timeSeconds, 0);
KeyFrame keyFrame = new KeyFrame(Duration.seconds(STARTTIME + 1), keyValue);
timeline.getKeyFrames().add(keyFrame);
timeline.playFromStart();
System.out.println("get every seconds value and display to console window");
}
});
from: http://www.asgteach.com/blog/?p=334
If you want to perform some other action when the actual value of timeSeconds changes, just add a listener to it:
timeSeconds.addListener((observable, oldTimeValue, newTimeValue) -> {
// code to execute here...
// e.g.
System.out.println("Time left: "+newTimeValue);
});
If you are changing the UI in response to the countdown changing value, though, a binding of the kind of already have is preferable, imho.