JavaFX Repeater - user-interface

I want to have something like a TimerTask in JavaFX.
I have a order of Functions, this Functions should be repeated every 1/2 Second maybe every 1/4 Second.
This Functions have some effects for a GUI Component in JavaFX.
Can you give me an TimerTask (JavaFX) example ? I can not use Timer Task, becouse the Compiler said this:
Exception in thread "Timer-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = Timer-0
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:237)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:398)
at javafx.scene.Parent$1.onProposedChange(Parent.java:245)
at com.sun.javafx.collections.VetoableObservableList.clear(VetoableObservableList.java:146)
at com.sun.javafx.charts.Legend$1.onChanged(Legend.java:55)
at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:134)
at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:48)
at com.sun.javafx.collections.ObservableListWrapper.callObservers(ObservableListWrapper.java:97)
at com.sun.javafx.collections.ObservableListWrapper.clear(ObservableListWrapper.java:184)
at javafx.scene.chart.AreaChart.updateLegend(AreaChart.java:420)
at javafx.scene.chart.XYChart$2.onChanged(XYChart.java:96)
at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:134)
at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:48)
at com.sun.javafx.collections.ObservableListWrapper.callObservers(ObservableListWrapper.java:97)
at com.sun.javafx.collections.ObservableListWrapper.removeFromList(ObservableListWrapper.java:383)
at com.sun.javafx.collections.ObservableListWrapper.removeAll(ObservableListWrapper.java:271)
at de.sick.suit.framework.control.fx.HistogramChart.deleteData(HistogramChart.java:170)
at de.sick.suit.framework.samples.ImageHistogram.run(ImageHistogram.java:200)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
Thank you for your help!

You can use a ScheduledService. The example from the javadoc:
you may want to ping a server on a regular basis to see if there are any updates. Such as ScheduledService might be implemented like this:
ScheduledService<Document> svc = new ScheduledService<>(Duration.seconds(1)) {
protected Task<Document> createTask() {
return new Task<Document>() {
protected Document call() {
// Connect to a Server
// Get the XML document
// Parse it into a document
return document;
}
}

// TIMER
Timeline line = new Timeline(new KeyFrame(Duration.seconds(0.2), new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent arg0)
{
sek++;
puls(imgHisto, startingArea);
System.out.println(" Sek: " + sek);
}
}));
line.setCycleCount(Animation.INDEFINITE);
line.play();
I handeld the Problem with a TimeLine. This works very fine for my example!

You need to provide more Code, but as of now I think you are not updating the UI properly. If you are in another Thread (which you seem to be if you are using a Task), whenever you want to update the UI you need to use
Platform.runLater();
Your Stacktrace indicates this.

You were updating GUI component outside the JavaFX application thread.
Try something like this
Platform.runLater(new Runnable(){
#Override
public void run(){
//update GUI here
}
});

Related

Performing Asynchronous operations on Vaadin UI

I have a Spring Boot project with Vaadin integration (v14). I want my application to do some background operation and represent the results on the Vaadin-based frontend. For this I have a view which is a Polymer template generated with Vaadin Designer (.js) and connected to a Java companion class. To this view I've just simply added a button initialized with the following listener:
_btnMyTriggerButton.addClickListener(event -> {
CompletableFuture<Void> c = CompletableFuture.supplyAsync(() -> {
for (int i = 0; i < 5; i++)
{
try
{
System.out.println("Waiting");
Thread.sleep(1000);
UI.getCurrent().access(() -> {
Notification.show("Waiting");
});
}
catch (InterruptedException e)
{
}
}
return "Waiting over. Greet!";
}).thenAccept(s -> {
System.out.println(s);
UI.getCurrent().access(() -> {
Notification.show(s);
});
});
I'm trying to access the UI as the documentation says. However when this is being executed it only reaches the first "Waiting", then stops. If I remove the UI interaction (Notification.show()) the output is printed to the backend as desired, but not when attempting do any interaction on the UI..
The structure of my java companion class is the following:
#Tag("my-view")
#JsModule("./my-view.js")
#Route("")
#Push(PushMode.AUTOMATIC)
public class MyView extends PolymerTemplate<MyView.MyModel>
{
#Id("trigger-button")
private Button _btnMyTriggerButton;
MyView() {
// listener initialization code described above
}
public interface MyModel extends TemplateModel
{
}
}
Do I miss something to achieve asynchronous behavior on this webpage?
Any help is appreciated.
The problem in this case is that the first callback terminates with a NullPointerException because UI.getCurrent() returns null when it's run from a background thread. CompletableFuture will just ignore the exception unless you explicitly handle it (e.g. using handle instead of thenAccept) or block on the result.
You can fix this by adding UI ui = UI.getCurrent(); in the beginning of the click listener and then referencing ui in both the supplyAsync and thenAccept callbacks instead of using UI.getCurrent() there.

Start then Stop Windows Service very fast, the OnStop method did not call

I am doing a windows service (call it SampleService), every is fine. When I started then stopped service through Windows Service Management Tool (service.msc), it run properly.
But my service will be request Start and Stop by another application. So I will not use Windows Service Management Tool in this case.
This is my service implement.
using System.ServiceProcess;
public partial class SampleService : ServiceBase
{
public SampleService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
this.WriteLog("OnStart");
// Doing start service logic down here
// Some service logic like create some files.
// Or just leave it empty like a brand new Windows Service.
}
protected override void OnStop()
{
this.WriteLog("OnStop");
// Doing clean service logic down here.
// Some service logic like: delete files.
// Or just leave it empty like a brand new Windows Service.
}
static readonly object synObject = new object();
public void WriteLog(string message)
{
if (string.IsNullOrEmpty(message))
{
return;
}
// Write log.
lock (synObject)
{
using (var wr = new StreamWriter(#"C:\logfile.txt", true))
{
wr.WriteLine(DateTime.Now + "-" + message);
}
}
}
}
And this is code logic use to Start and Stop service inside my another application. I can not modify this another application. The bellow source code simulate what happen.
class Program
{
static void Main(string[] args)
{
ServiceController sc = new ServiceController("SampleService");
// start service
sc.Start();
// doing some logic cost deltaTime or just stand by in deltaTime.
Thread.Sleep(deltaTime);
try
{
// stop service first time, nothing happen.
sc.Stop();
}
catch
{
}
try
{
// stop service second times, by dump people or apllication.
sc.Stop();
}
catch
{
// It got an exception here: "The service cannot accept control messages at this time".
// But the service did stopped.
}
}
}
The problem is:"When deltaTime is too short (bellow 3000ms with empty OnStart(), OnStop()), Service will stop incorrectly. The output log OnStop will never show up, that mean OnStop method did not called.
My service will doing clean up work in OnStop (like delete some file), but if it not be called, these files still there.
I cannot change logic of another application but I can change SampleService.
I want to ask:
Is this an Windows Service base issue and I cant do anything with it?
What ever it is, can I do clean up some where else?
Thank you!

Start specific view of Gluon App from a notification

I set up an alarm to show a corresponding Notification. The PendingIntent of the Notification is used to start the Gluon App main class. To show a View other than the homeView, I call switchView(otherView) in the postInit method. OtherView is shown, but without AppBar. While it's possible to make the AppBar appear, I wonder if this is the right approach.
#Override
public void postInit(Scene scene) {
// additional setUp logic
boolean showReadingView = (boolean) PlatformProvider.getPlatform().getLaunchIntentExtra("showReadingView", false);
if (showReadingView) {
switchView(READING_VIEW);
}
}
When triggering anything related to the JavaFX thread from another thread, we have to use Platform.runLater().
Yours is a clear case of this situation: the Android thread is calling some pending intent, and as a result, the app is started again.
This should be done:
#Override
public void postInit(Scene scene) {
// additional setUp logic
boolean showReadingView = (boolean) PlatformProvider.getPlatform().getLaunchIntentExtra("showReadingView", false);
if (showReadingView) {
Platform.runLater(() -> switchView(READING_VIEW));
}
}

Automatically detect when storing an object with ServiceStack.Redis

I am looking for a way to subscribe to events like Storing a specific object type to ServiceStack.Redis.
For example I may
using (var redisClient = new RedisClient())
using (var redisMyObjects = redisClient.As<MyObject>())
{
redisMyObjects.Store(myObject);//<-- I want this to trigger an event somehow
}
Is there anything like a OnStore event which I can hook too, anything out of the box? if not, is there any recommendation about how this should be done?
I don't think there is anything you can hook into (could be wrong).
Two options that came to mind:
1 - Make an extension method
2 - Publish a message to store your object and have a handler that listens for a response and does something. This is probably overkill since it's heading into the publish/subscribe realm. But, I think, worth looking into. (Basic example here and see Pub/Sub here).
Extension Method
public static class RedisClientExtensions
{
public static void StoreWithTrigger<T>(this IRedisTypedClient<T> redisClient, T value, Action<T> trigger)
{
redisClient.Store(value);
trigger(value);
}
}
Using ExtensionMethod
public void MyMethod()
{
using (var redisClient = new RedisClient())
using (var redisMyObjects = redisClient.As<MyObject>())
{
redisMyObjects.StoreWithTrigger<MyObject>(new MyObject(), TriggerEvent);//<-- I want this to trigger an event somehow
}
}
private void TriggerEvent<T>(T value)
{
//dosomething
}
Hope this gives you some ideas.

SWT: How do you register KeyUp events when no Control have focus?

Im am making an Java SWT program that is required to run on both Linux and Windows.
I use the following Code to listen for KeyUp events:
Control.addListener(SWT.KeyUp, new Listener() {
public void handleEvent(Event arg0) {
System.out.println("Event");
}
});
But this does not trigger when no control has focus.
Do anyone know of a place i can add a listener that acts as a Catch-all?
The only way of doing this that I'm aware of is by placing a filter on the Display. Take note that multiple Shells may operate on one Display, so you should be careful!
shell.getDisplay().addFilter(SWT.KeyDown, new Listener() {
public void handleEvent(final Event event) {
System.out.println(event);
}
});
try following method in Display class:
public void addListener ( int eventType, Listener listener )
I have not been able to find a solution to this. I suspect none exist

Resources