displaying dialog during module restore causes java.lang.IllegalStateException: no splash screen available - rcp

I have application built on top of Netbeans Platform and I need to do some checks during loading of one of the modules and display a dialog if some of the check fails to let the user to decide what should happen.
Insipired by this tutorial https://platform.netbeans.org/tutorials/60/nbm-login.html I created installer for the module and put the checks and dialog display to the installers method restore().
public class Installer extends ModuleInstall {
#Override
public void restored() {
if (check()) {
DialogDisplayer.getDefault().notify(myDialogDescriptor);
//...
}
}
This works but causes the splash screen to be closed and later there occurs an exception
java.lang.IllegalStateException: no splash screen available
at java.awt.SplashScreen.checkVisible(SplashScreen.java:197)
at java.awt.SplashScreen.update(SplashScreen.java:324)
at org.netbeans.core.startup.Splash$SplashPainter.repaint(Splash.java:401)
at org.netbeans.core.startup.Splash$SplashPainter$1.run(Splash.java:442)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
What can I do to prevent this exception?

I was able to reproduce this exception in a simple standalone module. This seems to be a known bug in NetBeans. A possible work around is to use WindowManager.invokeWhenUIReady() to delay display of the dialog until the main window opens like in this code example.
public class Installer extends ModuleInstall {
#Override
public void restored() {
WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
#Override
public void run() {
NotifyDescriptor.Confirmation dd = new NotifyDescriptor.Confirmation("Do you want to proceed?");
Object result = DialogDisplayer.getDefault().notify(dd);
if (result == DialogDescriptor.OK_OPTION) {
// Do something
}
}
});
}
But this workaround may not be acceptable if your requirement is to display the dialog and take action before the main window opens and is displayed.

Related

JavaFX image not changing when function is called by Platform.runLater

I have a function to change an image and its opacity in a JavaFX GUI:
private static Image image = null;
private static ImageView imageView = new ImageView();
// some code to add image in GUI
public static void changeImage() {
imageView.setOpacity(0.5);
imageView.setImage(null);
}
When I call this function within the JavaFX instance, the image disappears or is changing if I use an image instead of null for setImage(). I tried calling the function by pressing a button.
In this case all works as I expected.
When I call this function from another class, the actual image will change its opacity, but the image itself is never changing. I call the function the following way:
public static void changeImg() {
Platform.runLater(() -> FX_Gui.changeImage());
}
Changing labels, progess bars... all works, but I did not manage to change an image.
There's a lot of aspects to this question that don't make sense.
Generally speaking, the GUI in JavaFX is intended to be self-contained and non-linear in it's execution. Programming an outside method to assume some state of the GUI, and then to directly manipulate the GUI based on that assumption is not the correct approach. So any attempt to know the state of the GUI by kludging in a Thread.sleep() call is inherently incorrect.
The new JFXPanel() call is not needed, as Application.launch() will initialize JavaFX. Presumably, this was added before the sleep(500) was put in, since calling changeImg() would fail if run immediately after the Thread.start() command, since the launch() wouldn't have time to even start yet.
As has been noted, having some kind of startup image that's replaced once the screen completes initialization should be done from within the FX_Min.start(Stage) method, although it's highly unlikely that you'd even see the first image.
The question seems to be aimed at designing a kind of application where the GUI is just some small part of it and the main application is going to go on to do lengthy processing and then trigger the GUI to something in response to the results of that processing. Or perhaps the main application is monitoring an external API and feeding updates to GUI periodically. In most cases, however, the GUI is usually initialized so that it can take control of the operation, launching background threads to do the lengthy processing and using JavaFX tools to handle the triggering of GUI updates and intake of results.
In the instance that the design really needs to have something other than the GUI be the central control, then use of Application does not seem appropriate. It is, after all, designed to control the Application, and monitors the status of the GUI once it's been launched to shut everything down when the GUI is closed. This is why the OP had to put the Application.launch() call in a separate thread - launch() doesn't return until the GUI shuts down.
If the application outside of the GUI is going to control everything then it's best to manually start JavaFX with Platform.startup(), and handle all the monitoring manually. The following code doesn't do any monitoring, but it does start up the GUI and change the image without any issues:
public class Control_Min {
public static void main(String[] args) {
Platform.startup(() -> new Fx_Min().start(new Stage()));
Platform.runLater(() -> Fx_Min.changeImage());
}
}
Note that no changes are required to the OP's code in Fx_Min. However, there's no reason for Fx_Min to extend Application any more, and the code from its start() method can be placed anywhere.
It should be further noted that, although this works, it's really way outside the norm for JavaFX applications. It's possible that the OP's situation really does require this kind of architecture, but that would place it into a very small minority of applications. Designing the application around Application.launch() and initiating lengthy processing in background threads through the JavaFX tools provided is almost always a better approach.
OK, so given new information from the OP it's clear that this should be based on Application and that the GUI should launch some kind of socket listener that would presumably block waiting for input.
Anything that blocks can't run on the FXAT, and there needs to be a way to allow the socket listener to communicate back to the GUI when it receives data. Ideally, the socket listener should be JavaFX unaware, and just plain Java.
IMO, the best way to do this is to provide a Consumer to accept information from the socket listener, and to pass it to the socket listener in it's constructor. That way, the GUI knows nothing about the nature of the socket listener except that it has a dependency on requiring a message consumer. Similarly, the socket listener has no knowledge about what invoked it, just that it has given it a message consumer.
This limits your coupling, and you are free to write your GUI without worrying about any of the inner workings of the socket listener, and visa versa.
So here's the GUI, cleaned up and simplified a bit so that the socket listener stuff is easier to follow. Basically, the GUI is just going to throw the message from the socket listener into a Text already on the screen. The message consumer handles the Platform.runLater() so that the socket listener isn't even aware of it:
public class Fx_Min extends Application {
#Override
public void start(Stage primaryStage) {
ImageView imageView = new ImageView(new Image("/images/ArrowUp.png"));
Text text = new Text("");
primaryStage.setScene(new Scene(new VBox(10, imageView, text), 800, 600));
primaryStage.setResizable(true);
primaryStage.show();
imageView.setImage(new Image("/images/Flag.png"));
new SocketListener(socketMessage -> Platform.runLater(() -> text.setText(socketMessage))).startListening();
}
public static void main(String[] args) {
launch(args);
}
}
Here's the socket listener. Clearly, this isn't going to listen on a socket, but it loops around a sleep() to simulate action happening on the Pi. The message format here is String, just to keep everything simple, but obviously this is the worse possible choice for an actual implementation of this. Build a special message class:
public class SocketListener {
private Consumer<String> messageConsumer;
public SocketListener(Consumer<String> messageConsumer) {
this.messageConsumer = messageConsumer;
}
public void startListening() {
Thread listenerThread = new Thread(() -> listenForIRCommand());
listenerThread.setDaemon(true);
listenerThread.start();
}
private void listenForIRCommand() {
for (int x = 0; x < 100; x++) {
try {
Thread.sleep(5000);
messageConsumer.accept("Station " + x);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
It should be really clear that since the call to listenForIRCommand() is executed from inside a background thread, that it's completely freed from any JavaFX contstraints. Anything that generally possible in Java can be done from there without worrying about it's impact on the GUI.
In the meantime I found out that the reason for not changing the image is that I run changeImage() before the initialization of the GUI is completed. If I wait about 500 mS before I sent the changeImage() command all works fine.
Below is the minimal code that demonstrates the issue I had:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
public class Control_Min {
public static void changeImg() {
Platform.runLater(() -> Fx_Min.changeImage());
}
public static void main(String[] args) {
new Thread() {
public void run() {
Application.launch(Fx_Min.class);
}
}.start();
// JFXPanel will initialize the JavaFX toolkit.
new JFXPanel();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
changeImg();
}
}
And the Gui itself:
public class Fx_Min extends Application {
private static Stage stage;
private static GridPane rootPane;
private static Scene scene;
private static Image image = null;
private static ImageView imageView = new ImageView();
#Override
public void start(Stage primaryStage) {
stage = primaryStage;
rootPane = new GridPane();
scene = new Scene(rootPane,800,600);
try {
image = new Image(new FileInputStream("C:\\Users\\Peter\\eclipse-workspace\\FX_Test\\src\\application\\Image1.jpg"));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
imageView.setImage(image);
rootPane.add(imageView, 1, 0);
stage.setScene(scene);
stage.setResizable(true);
stage.show();
System.out.println("Gui is ready");
}
public static void changeImage() {
try {
image = new Image(new FileInputStream("C:\\Users\\Peter\\eclipse-workspace\\FX_Test\\src\\application\\Image2.jpg"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
imageView.setImage(image);
System.out.println("Image Changed");
}
public static void main(String[] args) {
launch(args);
}
}
This code works fine.
In the console I get:
Gui is ready
Image Changed
When I remove the Thread.sleep(500) the image will not change.
In the console I get:
Image Change
Gui is ready
My conclusion is that I have send the runlater method before the FX runtime has been initialized.
(Have not fixed the static issue yet as this was not the issue. I will do in my original program later.)
My task is the following:
I program a GUI for my internet radio player on my PC.
The GUI controls the radio and polls what is playing.
I want to control the radio by an IR remote control too.
I have already a Raspberry Pi that communicates with the remote.
Therefore, my plan is to run a server socket on the PC, that receives the commands from the Raspberry Pi.
The server will run in its own thread. I want to use the runLater command to update the GUI.
Is there a better way to update the GUI from the server?
Goal is that the GUI will update immediately when I press a button on the remote.
With my latest learnings about JavaFX I will start the application now directly in the FX class and get the server thread started from the FX class

activity did not call through super.onresume exception

In my xamarin forms app, there is crash which is as follows from App Center crashlytics:
android.app.Activity.performResume:
Activity.java - line 7138
android.util.SuperNotCalledException: Activity
{com.tcrsoftware.androidx/md54f7a5b50cfc6839da41f22f8e0e378f9.MainActivity}
did not call through to super.onResume()
android.app.Activity.performResume Activity.java:7138
android.app.ActivityThread.performResumeActivity ActivityThread.java:3850
android.app.ActivityThread.handleResumeActivity ActivityThread.java:3914
android.app.ActivityThread$H.handleMessage ActivityThread.java:1709
android.os.Handler.dispatchMessage Handler.java:102
android.os.Looper.loop Looper.java:154
android.app.ActivityThread.main ActivityThread.java:6823
java.lang.reflect.Method.invoke Method.java
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run
ZygoteInit.java:1557
com.android.internal.os.ZygoteInit.main ZygoteInit.java:1445
I just use onResume() in my Shared Library project like:
public partial class App : Application
{
protected override void OnResume()
{
Utility.LogMessage("OnResume: ", LogMessageType.info);
}
}
I did not implement/use onResume() in the MainActivity class of android project.
Where and why this crash occured? And also would it be cause app to crash continously when user tries to open the app?
any updates?

Getting Java.Lang.NullPointerException when trying to open GPS Settings page using Xamarin

I am getting the following error when trying to open GPS settings page if GPS is not enabled (within Xamarin):
Unknown identifier: StartActivity
Unhandled Exception:
Java.Lang.NullPointerException:
Can somebody please guide where am I getting wrong?
This My Interface
namespace MyApp
{
public interface GpsSettings
{
void showGpsSettings();
}
}
This the Implementation
[assembly: Xamarin.Forms.Dependency(typeof(GpsSettingsImplementation))]
namespace MyApp.Droid
{
public class GpsSettingsImplementation : Activity, GpsSettings
{
public GpsSettingsImplementation()
{
}
public void showGpsSettings()
{
var intent = new Intent(Android.Provider.Settings.ActionLocationSourceSettings);
StartActivity(intent);
}
}
}
This is how I call my function on button click
DependencyService.Get<GpsSettings>().showGpsSettings();
An existing Activity instance has a bit of work that goes on behind
the scenes when it's constructed; activities started through the
intent system (all activities) will have a Context reference added to
them when they are instantiated. This context reference is used in the
call-chain of StartActivity.
So, the Java.Lang.NullPointerException seen after invoking
StartActivity on your Test activity instance is because the Context
inside that instance has never been set. By using the new operator to
create an activity instance you've circumvented the normal way
activities are instantiated, leaving your instance in an invalid
state!
ref: https://stackoverflow.com/a/31330999/5145530
The above error can be resolved in the following manner:
[assembly: Xamarin.Forms.Dependency(typeof(GpsSettingsImplementation))]
namespace MyApp.Droid
{
public class GpsSettingsImplementation : Activity, GpsSettings
{
public GpsSettingsImplementation()
{
}
public void showGpsSettings()
{
var intent = new Intent(Android.Provider.Settings.ActionLocationSourceSettings);
intent.SetFlags(ActivityFlags.NewTask);
Android.App.Application.Context.StartActivity(intent);
}
}
}

Interoperability problems when using JavaFx combobox within SWT Dialog

JavaFx is supposed to be easily integrated in an SWT application (see here: http://docs.oracle.com/javafx/2/swt_interoperability/jfxpub-swt_interoperability.htm) and both toolkits use the same threading model.
However things get strange, when I open a dialog containing an FxCanvas which contains a JavaFx ComboBox. If I open the combo box popup menu and then close the dialog, the popup menu stays open. If I now move the mouse onto the popup a null pointer exception is thrown within javafx. When doing this within a larger application all JavaFx GUIs remain broken until the application is restarted.
Any ways to work around this?
Example code below: Close the dialog with 'Ok' or the window close button. Exit the application with 'Cancel'
package test;
import javafx.embed.swt.FXCanvas;
import javafx.geometry.Insets;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.StackPane;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class TestFx {
static class MyDialog extends Dialog {
Parent w;
public MyDialog(Shell parent,Parent n) {
super(parent);
this.w = n;
setShellStyle(SWT.RESIZE| SWT.BORDER | SWT.TITLE |SWT.CLOSE );
}
#Override
public void cancelPressed() {
System.exit(0);
}
#Override
protected Control createDialogArea(Composite parent) {
Composite container = (Composite) super.createDialogArea(parent);
container.setLayout(new FillLayout());
FXCanvas fxCanvas = new FXCanvas(container, SWT.NONE);
Scene scene = new Scene(w);
fxCanvas.setScene(scene);
return container;
}
}
private static Parent createScene() {
StackPane pane = new StackPane();
pane.setPadding(new Insets(10));
ComboBox<String> c = new ComboBox<String>();
c.getItems().addAll("Test1","Test2");
pane.getChildren().add(c);
return pane;
}
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
while (true) {
MyDialog d = new MyDialog(shell,createScene());
d.open();
}
}
}
Exception:
java.lang.NullPointerException
at com.sun.javafx.tk.quantum.GlassScene.sceneChanged(GlassScene.java:290)
at com.sun.javafx.tk.quantum.ViewScene.sceneChanged(ViewScene.java:156)
at com.sun.javafx.tk.quantum.PopupScene.sceneChanged(PopupScene.java:30)
at com.sun.javafx.tk.quantum.GlassScene.markDirty(GlassScene.java:157)
at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2214)
at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:363)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:460)
at com.sun.javafx.tk.quantum.QuantumToolkit$9.run(QuantumToolkit.java:329)
at org.eclipse.swt.internal.win32.OS.DispatchMessageW(Native Method)
at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:2546)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3756)
at org.eclipse.jface.window.Window.runEventLoop(Window.java:825)
at org.eclipse.jface.window.Window.open(Window.java:801)
at test.TestFx.main(TestFx.java:55)
At work we're developing some applications using JavaFX, on top of and old Swing platform and we also have found this issue.
Apparently it is caused by some issues on JFXPanel which is not correctly propagating some window events (focus, iconifying, etc) to the FX framework. The issue affects not only the ComboBox component, but every component that uses a PopupWindow (Menu, Tooltip, etc), specially when using Swing's JInternalFrame.
So, when a Popup is displaying and the window is minimized or closed, the Popup does not hide, causing the FX thread to crash if you try subsequently to interact with it.
The workaround mentioned above works, but only for ComboBox, as Menu and Tooltip does not inherit from the Node class, so didn't work for us :(
I developed another workaround which resolved the problem for all components that display popups, which basically forces all popups to close whenever a JFXPanel loses focus:
private static void initFX(final JFXPanel jfxPanel) {
final TestFxPanel parent = new TestFxPanel();
final Scene scene = new Scene(parent);
jfxPanel.setScene(scene);
jfxPanel.addFocusListener(new FocusAdapter() {
#Override
public void focusLost(final FocusEvent e) {
System.out.println(jfxPanel.getName() + ": FocusLost");
runFocusPatch(scene);
}
});
}
static void runFocusPatch(final Scene scene) {
Platform.runLater(new Runnable() {
#Override
public void run() {
System.out.println("Running patch");
final Iterator<Window> winIter = scene.getWindow().impl_getWindows();
while (winIter.hasNext()) {
final Window t = winIter.next();
if (t instanceof PopupWindow) {
System.out.println("Got a popup");
Platform.runLater(new Runnable() {
#Override
public void run() {
((PopupWindow) t).hide();
}
});
}
}
}
});
}
I confirm that the issue is NOT present in 8.0. Sadly we are not allowed to java 8 in production software as its still in beta stage.
best regards.
I found a workaround when using Java7: Override the close method in Dialog to hide the combo box popups:
#Override
public boolean close() {
Set<Node> nodes = w.lookupAll("#");
for (Node n : nodes)
if (n instanceof ComboBox)
((ComboBox)n).hide();
return super.close();
}
The trouble is discussed here : javafx-jira.kenai.com/browse/RT-30991
Developer has said, that the issue is fixed in JavaFX-8

Shared Toast does not show in Android 3.0.1 on Motorola Xoom

I use a shared Toast across different Activities in order to only show the latest message, immediately discarding any previous ones. I put the code in the custom Application object:
public class GameApp extends Application {
private Toast mToast;
#Override
public void onCreate() {
super.onCreate();
mToast = Toast.makeText(getApplicationContext(), "", Toast.LENGTH_SHORT);
}
public void displayToast(int textId) {
displayToast(getText(textId));
}
public void displayToast(CharSequence text) {
mToast.cancel();
mToast.setText(text);
mToast.show();
}
}
The Toast showed up on my 1.6, 2.2, and 3.0 emulators. But when I downloaded the released app from the Market, it only shows on my G1 (CyanMod 6.1) but not Xoom (3.0.1). I tried connecting the Xoom with USB debugging, but nothing relevant showed up in LogCat.
Prior to this, I used to do Toasts the conventional way (i.e. via Toast.makeText()) and that worked on everything as expected.
Could there be any potential problem with my above code, or could this be a bug in the Xoom? Here is the link to my app, in case you want to test it. The Toast should show up when you click Today, Progress in the Main screen. I appreciate any help. Thank you very much :)
i'm not sure but the sdk that motorola uses may be different.. and mToast.cancel() could be doin something terrible.. so have you tried this..
public void displayToast(CharSequence text) {
mToast.setText(text);
mToast.show();
}
This is because that mToast.cancel(); may close the toast if it's showing, or don't show it if it isn't showing yet.
Please create new Toast object when users click buttons. And keep the previous Toast object reference. Next time when user click buttons, cancel the previous Toast object and create new Toast again.
public class GameApp extends Application {
private Toast mToast;
private Context mContext;
#Override
public void onCreate() {
super.onCreate();
mToast = Toast.makeText(getApplicationContext(), "", Toast.LENGTH_SHORT);
}
public void displayToast(int textId,Context mContext) {
this.mContext = mContext;
displayToast(getText(textId));
}
public void displayToast(CharSequence text) {
mToast.cancel();
mToast = new Toast(mContext);
mToast.setText(text);
mToast.setDuration(Toast.LENGTH_SHORT);
mToast.show();
}
}

Resources