I am working on a clock program in Java and I am unsure how to make the time update secondly. I have tried using a for loop with thread.sleep(1000); but that did not work. Also, if anybody knows how to stop the Stage from opening in white then having a small delay before turning black, that would be really appreciated.
Here is my code:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.scene.paint.Color;
import javafx.scene.layout.HBox;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import java.text.DateFormat;
import java.util.Date;
import java.text.SimpleDateFormat;
public class Clock extends Application {
#Override public void start(Stage stage) {
DateFormat df = new SimpleDateFormat("EEE,MMM d yyyy - h:mm:ss a");
Date date = new Date();
String stringDate = df.format(date);
Text text = new Text(10, 60, stringDate);
text.setFont(Font.font ("Digital Dream Fat", 30f));
text.setFill(Color.RED);
HBox hbox = new HBox();
Scene scene = new Scene(new Group(text));
scene.setFill(Color.BLACK);
stage.setScene(scene);
stage.initStyle(StageStyle.UNDECORATED);
stage.setWidth(710);
stage.setHeight(80);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
First of all, you have to remember that UI's components are not thread-safe thus any update operations on the ui must be done within the ui's thread itself and not from background threads otherwise they will block the UI's thread.
To update it you can use thread safe mechanisms, one of them is Timeline class. Let's now implement it in your code.
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.scene.paint.Color;
import javafx.scene.layout.HBox;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import java.text.DateFormat;
import java.util.Date;
import java.text.SimpleDateFormat;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.util.Duration;
public class Clock extends Application {
#Override public void start(Stage stage) {
DateFormat df = new SimpleDateFormat("EEE,MMM d yyyy - h:mm:ss a");
Date date = new Date();
String stringDate = df.format(date);
Text text = new Text(10, 60, stringDate);
text.setFont(Font.font ("Digital Dream Fat", 30f));
text.setFill(Color.RED);
HBox hbox = new HBox();
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(0),
new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
Date update = new Date();
String stringNewDate = df.format(update);
text.setText(stringNewDate);
}
}
), new KeyFrame(Duration.seconds(1)));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play(); // timeline.stop()
Scene scene = new Scene(new Group(text));
scene.setFill(Color.BLACK);
stage.setScene(scene);
stage.initStyle(StageStyle.UNDECORATED);
stage.setWidth(710);
stage.setHeight(80);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The sleep/pause part is controlled on this line .. new KeyFrame(Duration.seconds(1))) so every minute will be Duration.minutes(1), to stop it just take Timeline's instance then do timeline.stop()
You have to setup a TimerTask and run it in a separate thead.
https://docs.oracle.com/javase/7/docs/api/java/util/TimerTask.html
TimerTask can't update the JavaFX Label text
Related
import javafx.animation.FillTransition;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.ParallelTransition;
import javafx.animation.Timeline;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.effect.BoxBlur;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;
public class NewFXMain extends javafx.application.Application {
#Override
public void start(Stage primaryStage) {
var pane = new Pane();
var rectangle = new Rectangle(300, 100, 400, 400);
var text = new Text(100, 100, "Java");
rectangle.setOnMouseEntered((event) -> {
var fill = new FillTransition(Duration.millis(1000), rectangle, (Color) rectangle.getFill(), Color.GREEN);
var timeline = new Timeline(new KeyFrame(Duration.millis(1000), new KeyValue(text.effectProperty(), new BoxBlur(4, 4, 4))));
var transition = new ParallelTransition(fill, timeline);
transition.play();
});
pane.getChildren().addAll(rectangle, text);
Scene scene = new Scene(pane, 1000, 720, true, SceneAntialiasing.BALANCED);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This code should create an animation to change the color of the rectangle and blur the text.
However, while FillTransition works perfectly well, BoxBlur effect occurs without animation after 1 second.
How do I write effectProperty correctly to create an animation?
Please help.
Thank you
None of the Effect classes, as of JavaFX 12, implement Interpolatable. This means the animation can't gradually go from no effect to an end effect, thus your animation jumps from null to BoxBlur. You should animate the properties of the BoxBlur instance, rather than the effect property itself.
Here's an example:
import javafx.animation.FillTransition;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.ParallelTransition;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.effect.BoxBlur;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;
public final class App extends Application {
#Override
public void start(Stage primaryStage) {
var rectangle = new Rectangle(150, 100);
var text = new Text("Hello, World!");
text.setFill(Color.WHITE);
var effect = new BoxBlur(0, 0, 1);
text.setEffect(effect);
var animation = new ParallelTransition(
new FillTransition(Duration.seconds(1), rectangle, Color.BLACK, Color.GREEN),
new Timeline(
new KeyFrame(Duration.ZERO,
new KeyValue(effect.widthProperty(), 0),
new KeyValue(effect.heightProperty(), 0)
),
new KeyFrame(Duration.seconds(1),
new KeyValue(effect.widthProperty(), 10),
new KeyValue(effect.heightProperty(), 10)
)
)
);
rectangle.setOnMouseEntered(event -> {
event.consume();
animation.setRate(1);
animation.play();
});
rectangle.setOnMouseExited(event -> {
event.consume();
animation.setRate(-1);
animation.play();
});
primaryStage.setScene(new Scene(new StackPane(rectangle, text), 500, 300));
primaryStage.show();
}
}
We are currently working on a JavaFX Project for which we need to implement Text animation like movement from Left to Right with variant speeds. Execution environment for the application is an Embedded device - Stick PC.
We have used Translate Transition API https://docs.oracle.com/javase/8/javafx/api/javafx/animation/TranslateTransition.html for achieving animation effect but we are facing smoothness issues in it. Text is moving with jerks and movement speed is slow compared to animation in Laptop/Desktop
package application;
import javafx.animation.Interpolator;
import javafx.animation.Timeline;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.scene.CacheHint;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.stage.Stage;
public class SampleAnimationTest extends Application {
// private final Logger logger = Logger.getLogger("genLog");
#Override
public void start(Stage primaryStage) throws Exception {
StackPane group = new StackPane();
Rectangle rectangle = new Rectangle();
rectangle.setHeight(1080);
rectangle.setWidth(1920);
rectangle.setFill(Color.WHITE);
rectangle.setTranslateX(0);
rectangle.setTranslateY(0);
rectangle.setCache(true);
rectangle.setCacheHint(CacheHint.SPEED);
Text text = new Text("THIS IS A LONG TEXT FOR TESTING TEXT ANIMATION IN JAVAFX");
text.setFill(Color.BLACK);
text.setUnderline(false);
text.setFont(Font.font("Meiryo", 509.3899));
text.setTextAlignment(TextAlignment.CENTER);
text.setCache(true);
text.setCacheHint(CacheHint.SPEED);
TranslateTransition tt = new TranslateTransition();
tt.setNode(text);
Rectangle rClip = new Rectangle();
rClip.setWidth(rectangle.getWidth());
rClip.setHeight(rectangle.getHeight());
rClip.translateXProperty().bind(rectangle.translateXProperty());
group.getChildren().add(rectangle);
group.getChildren().add(text);
group.setClip(rClip);
Group group2 = new Group();
group2.getChildren().add(group);
Scene scene = new Scene(group2, 1920, 1080);
primaryStage.setMaximized(true);
primaryStage.setTitle("Decorations Example");
primaryStage.setScene(scene);
primaryStage.show();
tt.fromXProperty().bind(rectangle.translateXProperty().add(rectangle.getLayoutBounds().getWidth()));
tt.toXProperty().bind(rectangle.translateXProperty().subtract(text.getLayoutBounds().getWidth()));
tt.setRate(0.077364);
tt.setInterpolator(Interpolator.LINEAR);
tt.setCycleCount(Timeline.INDEFINITE);
tt.playFromStart();
}
public static void main(String[] args) {
launch(args);
}
}
I have made a desktop clock app in java which uses a specific font (Digital Dream Fat) in order to achieve the desired look but if someone doesn't have the font installed on their computer, it will default with Arial. How would I compensate for that?
Here is my code:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.collections.FXCollections;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Tooltip;
import javafx.stage.StageStyle;
import javafx.scene.paint.Color;
import javafx.scene.layout.HBox;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import java.text.DateFormat;
import java.util.Date;
import java.text.SimpleDateFormat;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.util.Duration;
public class Clock extends Application {
public Text text;
#Override
public void start(Stage stage) {
DateFormat df = new SimpleDateFormat("EEE,MMM d yyyy - h:mm:ss a");
Date date = new Date();
String stringDate = df.format(date);
text = new Text(10, 60, stringDate);
text.setFont(Font.font ("Digital Dream Fat", 30f));
text.setFill(Color.RED);
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(0), new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
Date update = new Date();
String stringNewDate = df.format(update);
text.setText(stringNewDate);
}
}), new KeyFrame(Duration.seconds(1)));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
ChoiceBox colorChoice = new ChoiceBox(FXCollections.observableArrayList("Red", "Blue", "Green", "Grey", "Black", "White"));
colorChoice.setOnAction(new EventHandler<ActionEvent>(){
public void handle(ActionEvent e) {
if (colorChoice.getSelectionModel().getSelectedItem().toString().equals("Red")) {
colorChoice.setStyle("-fx-base: red");
text.setFill(Color.RED);
} else if (colorChoice.getSelectionModel().getSelectedItem().toString().equals("Blue")) {
colorChoice.setStyle("-fx-base: blue");
text.setFill(Color.BLUE);
} else if (colorChoice.getSelectionModel().getSelectedItem().toString().equals("Green")) {
colorChoice.setStyle("-fx-base: green");
text.setFill(Color.GREEN);
} else if (colorChoice.getSelectionModel().getSelectedItem().toString().equals("Grey")) {
colorChoice.setStyle("-fx-base: grey");
text.setFill(Color.GREY);
} else if (colorChoice.getSelectionModel().getSelectedItem().toString().equals("White")) {
colorChoice.setStyle("-fx-base: white");
text.setFill(Color.WHITE);
} else if (colorChoice.getSelectionModel().getSelectedItem().toString().equals("Black")) {
colorChoice.setStyle("-fx-base: black");
text.setFill(Color.BLACK);
} else {
colorChoice.setStyle("-fx-base: red");
text.setFill(Color.RED);
}
}
});
HBox hbox = new HBox(colorChoice);
colorChoice.setTooltip(new Tooltip("Select A Colour"));
colorChoice.getSelectionModel().selectFirst();
Scene scene = new Scene(new Group(text, hbox));
scene.setFill(Color.TRANSPARENT);
stage.setScene(scene);
stage.initStyle(StageStyle.TRANSPARENT);
stage.setX(0);
stage.setY(0);
stage.setWidth(710);
stage.setHeight(80);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I am making an alarm clock kind of program and I need a way to make the clock face a specific font. I have tried multiple times in multiple ways. If that is not possible can you please provide another solution? Thank you in advance!
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.print.DocFlavor.URL;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Menu extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
//Frame stuff (works)
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setHgap(10);
grid.setVgap(10);
//Frame Size
Scene scene = new Scene(new DigitalClock(),1080, 720);
//Icon
primaryStage.getIcons().add(new Image(getClass().getResourceAsStream(("/lib/logo.png"))));
primaryStage.setTitle("Clock: 140 Edition");
//Necessities
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String args[]) {
launch(args);
}
}
class Util {
public static String pad(int fieldWidth, char padChar, String s) {
StringBuilder sb = new StringBuilder();
for (int i = s.length(); i < fieldWidth; i++) {
sb.append(padChar);
}
sb.append(s);
return sb.toString();
}
}
class DigitalClock extends Label {
public DigitalClock() {
bindToTime();
}
// the digital clock updates once a second.
private void bindToTime() {
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds(0),
new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent actionEvent) {
Calendar time = Calendar.getInstance();
String hourString = Util.pad(2, ' ', time.get(Calendar.HOUR) == 0 ? "12" : time.get(Calendar.HOUR) + "");
String minuteString = Util.pad(2, '0', time.get(Calendar.MINUTE) + "");
String secondString = Util.pad(2, '0', time.get(Calendar.SECOND) + "");
String ampmString = time.get(Calendar.AM_PM) == Calendar.AM ? "AM" : "PM";
setText(hourString + ":" + minuteString + ":" + secondString + " " + ampmString);
}
}
),
new KeyFrame(Duration.seconds(1))
);
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
}
I also know some of the imports are not used, I would prefer to keep them. Thanks again!
🍒The Font has to do with the Label you are using in the example.
Must
read:http://www.guigarage.com/2014/10/integrate-custom-fonts-javafx-application-using-css/
<-----------------Ways to do----------------->
1)Using external css:
/*The font path*/
#font-face{
src: url("../fonts/Younger than me Bold.ttf");
}
/* An element which has this id*/
#LabelID{
-fx-font-family:"Younger than me";
-fx-font-size:18.0;
}
//or for all labels
.label{
-fx-font-family:"Younger than me";
-fx-font-size:18.0;
}
2)Using setStyle(...):
`label.setStyle("-fx-font-family:monospace; -fx-font-size:16px; -fx-text-fill:black; -fx-border-color:red;");`
3)Using setFont(...):
b.setFont(new Font("Arial", 24));
4)Tricky and not recommended ( not included in JavaFX docs) : here
Relative posts:
How to set custom fonts in JavaFX Scene Builder using CSS
https://blog.idrsolutions.com/2014/04/use-external-css-files-javafx/
Have a look at https://gist.github.com/jewelsea/2658491
I'm trying to make a "launcher" with javafx.
This is my code :
I'm not shure you have to read all of this code, this code is here.
I'm trying to put a javaFX "play" button (i know how to make a button and how to set up an onclick event but i don't know where to add it :/)
Have you got an idea ? Thx.
package fr.whiteplay.main.launcher;
public class Launcher{
private static WebViewSample launcher;
private static String[] a;
public static void main(String[] args){
launcher = new WebViewSample();
a = args;
}
public static void start(){
launcher.go(a);
}
}
package fr.whiteplay.main.launcher;
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
public class WebViewSample extends Application{
private Browser browser;
private Scene scene;
public void start(Stage stage){
// create the scene
stage.setTitle("WhitePlay");
browser = new Browser();
scene = new Scene(browser, 992, 620, Color.web("#000000"));
stage.setScene(scene);
stage.show();
}
public static void go(String[] args){
launch(args);
}
}
package fr.whiteplay.main.launcher;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
class Browser extends Region{
final WebView browser = new WebView();
final WebEngine webEngine = browser.getEngine();
public Browser(){
getStyleClass().add("browser");
webEngine.load("http://www.whiteplay.fr/launcher/index.html");
getChildren().add(browser);
}
private Node createSpacer(){
Region spacer = new Region();
HBox.setHgrow(spacer, Priority.ALWAYS);
return spacer;
}
protected void layoutChildren(){
layoutInArea(browser, 0, 0, getWidth(), getHeight(), 0, HPos.CENTER, VPos.CENTER);
}
}
Instead of the browser itself, the scene root must be a structured panel, which contains the browser, the button, and whatever else.
The simplest example is to replace your WebViewSample.start() method with the following:
public void start(Stage stage){
// create the scene
stage.setTitle("WhitePlay");
browser = new Browser();
BorderPane root = new BorderPane();
root.setCenter(browser);
Button button = new Button("Play");
root.setBottom(button);
button.setOnAction(a -> System.out.println("Play"));
scene = new Scene(root, 992, 620, Color.web("#000000"));
stage.setScene(scene);
stage.show();
}
Check this page for further reference on various layouts options, and how to work with them.