I could not get TrayNotification
to work with the latest version of JavaFX
. I used ControlsFX
Notification
. The ideas should be very similar.
Use ScheduledService
to periodically check new db notifications. If ScheduledService
finds new notifications, stop ScheduledService
from looking for new notifications. Display the current notifications using Timeline
. Restart the ScheduledService
once the Timeline
finishes displaying the current notifications.
Main
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.util.Duration;
import org.controlsfx.control.Notifications;
public class App extends Application {
static List<MyNotification> myNotifications = new ArrayList();
static FakeDatabaseHandler fakeDatabaseHandler = new FakeDatabaseHandler();
@Override
public void start(Stage stage) {
Button btnGenerateNotification = new Button("Generate!");
btnGenerateNotification.setOnAction(actionEvent ->{
fakeDatabaseHandler.addFakeNotificationsToDb();
});
Label lblUpdateMessage = new Label("Update Message: ");
ScheduledService<List<MyNotification>> checkForScheduledService = new CheckForNotificationsScheduledService();
checkForScheduledService.setPeriod(Duration.seconds(5));
checkForScheduledService.messageProperty().addListener((ov, oldValue, newValue) -> {
if(newValue != null)
{
lblUpdateMessage.setText("Update Message: " + newValue);
}
});
checkForScheduledService.valueProperty().addListener((ov, oldValue, newValue) -> {
if(newValue != null && !newValue.isEmpty())
{
myNotifications.clear();
myNotifications.addAll(newValue);
checkForScheduledService.cancel();
AtomicInteger index = new AtomicInteger(0);
checkForScheduledService.cancel();
Timeline threeSecondsWonder = new Timeline(
new KeyFrame(Duration.seconds(3), event -> {
MyNotification myNotification = myNotifications.get(index.getAndIncrement());
Notifications.create().title(myNotification.getDepartment() + " - " + myNotification.getTitle()).text(myNotification.getMessage()).hideAfter(Duration.seconds(3)).showWarning();
})
);
threeSecondsWonder.setCycleCount(myNotifications.size());
threeSecondsWonder.play();
threeSecondsWonder.setOnFinished((t) -> {
checkForScheduledService.restart();
});
}
});
checkForScheduledService.start();
StackPane root = new StackPane(new VBox(btnGenerateNotification, lblUpdateMessage));
stage.setScene(new Scene(root, 500, 500));
stage.setTitle("Facilities");
stage.show();
}
public static void main(String[] args) {
launch(args);
}
private static class CheckForNotificationsScheduledService extends ScheduledService<List<MyNotification>> {
@Override
protected Task<List<MyNotification>> createTask() {
return new Task<List<MyNotification>>() {
@Override
protected List<MyNotification> call() throws Exception {
List<MyNotification> fakeNotificationList = fakeDatabaseHandler.getFakeNotificationsFromDB();
System.out.println("Checking for notifications. Notifications Found: " + fakeNotificationList.size());
updateMessage("Checking for notifications. Notifications Found: " + fakeNotificationList.size());
updateValue(fakeNotificationList);
return fakeNotificationList;
}
};
}
}
}
MyNotification
/**
*
* @author Sed
*/
public class MyNotification {
private String department;
private String title;
private String message;
public MyNotification(String department, String title, String message) {
this.department = department;
this.title = title;
this.message = message;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("MyNotification{");
sb.append("department=").append(department);
sb.append(", title=").append(title);
sb.append(", message=").append(message);
sb.append('}');
return sb.toString();
}
}
FakeDatabaseHandler
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
/**
*
* @author Sed
*/
public class FakeDatabaseHandler {
private final List<MyNotification> fakeDBData = new ArrayList();
//private Connection connection;
public FakeDatabaseHandler() {
//Estiblish the connection here
/*
try {
connection = DriverManager.getConnection("jdbc:sqlite:vbms_db.db");
System.out.println("Connected to SQLite Db: vbms_db.db");
}
catch (SQLException ex) {
System.out.println(ex.toString());
}
*/
}
public void addFakeNotificationsToDb(){
List<String> departmentList = Arrays.asList("A", "B", "C", "D");
//Use a PreparedStatement here! I am not gonig to demo that!
//Generating Fake DB data!
for(int i = 0; i < ThreadLocalRandom.current().nextInt(1, 6); i++)
{
int notificationID = ThreadLocalRandom.current().nextInt( 1000000);
fakeDBData.add(new MyNotification("Department: " + departmentList.get(ThreadLocalRandom.current().nextInt(4)), "Title " + notificationID, "Message: " + notificationID));
}
}
public List<MyNotification> getFakeNotificationsFromDB(){
List<MyNotification> returnList = new ArrayList(fakeDBData);
fakeDBData.clear();
return returnList;
}
}
Module-Info
module sed.home.simpletestjavafx {
requires javafx.controls;
requires org.controlsfx.controls;
exports sed.home.simpletestjavafx;
}
Output
