Location of stylesheet for javafx development
I've create my very first javafx extension and it's running but looks ugly as sin lol. I created a stylesheet to style the window (beautifully, if I do say so myself) but now I'm at a loss as to where to put it so that the extension can find it.
When I debug, there's an error :
Aug. 05, 2020 6:44:26 P.M. com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
WARNING: Resource "DailyPerformance.css" not found.
I've tried putting the css file in the extension folder, everywhere in the moneydance folders but nothing works.
Of course, this may all be because I don't know what I'm doing, and I'm not sure how the build process works with an extension. Can it be bundeld 'inside' the extension? Any help is gratefully accepted.
Comments are currently closed for this discussion. You can start a new one.
Keyboard shortcuts
Generic
? | Show this help |
---|---|
ESC | Blurs the current field |
Comment Form
r | Focus the comment reply box |
---|---|
^ + ↩ | Submit the comment |
You can use Command ⌘
instead of Control ^
on Mac
1 Posted by Bob B on 07 Aug, 2020 02:34 AM
I finally got this working in debug mode - window is styled nicely. To fix the issue I had to play around with the path and make also made sure the path was in the build file. However, since the css file is in the extension file, I don't know how to have it reference on the user's might configure (not a biggie, just wondering).
BUT the bigger issue is that I can only run in debug mode from Intellij. When I try to run from MD directly and not in debug mode, the extension dialog opens but is empty and when I close the dialog, MD also shuts down.
Is there anyway that i can 'debug' running version of MD? Can I somehow use the -d option when I start it and have the output go to text file? This is all new to me so any help is appreciated greatly.
Support Staff 2 Posted by Sean Reilly on 07 Aug, 2020 08:40 AM
As for quitting when you close the window, do you need to ensure that the exitOnClose setting is false on one of your windows? I'm not familiar with javafx so I'm just guessing on that.
By default all logging to stderr/stdout will go to the errlog.txt file that is stored in moneydance's internal folder. If you can monitor that file then I suppose there's no need for passing the -d flag. If you'd like to also enable moneydance's own internal logging to stderr (and also that file) you can set
com.moneydance.apps.md.controller.Main.DEBUG = true
--
Sean Reilly
Developer, The Infinite Kind
https://infinitekind.com
3 Posted by Mike Bray (Quot... on 07 Aug, 2020 09:23 AM
I am playing with JavaFX and have found a number of issues. Firstly MD has a class loader class that is used to load extensions. Not all of the ClassLoader methods are overridden so these don't work. If you set the FX Scene stylesheet these are not loaded. You need to load your .css file separately and set the style on the root node.
Secondly I use Eclipse as my IDE and when running in debug mode the resources are not found as the class hierarchy is different.
I must admit I have been considering switching back to Swing as using FX with the JFXPanel class causes some issues, especially with data access as this must be done on the Swing EDT.
4 Posted by Bob B on 07 Aug, 2020 05:31 PM
This is the error I'm getting when running directly from the app - It cant seem to find the loaded class.
prior to loader creation
Exception in thread "JavaFX Application Thread" java.lang.NoClassDefFoundError: javafx/fxml/FXMLLoader
Here is the source:
System.err.println("prior to loader creation");
FXMLLoader loader = new FXMLLoader();
System.err.println("new FXMLoader created");
loader.setLocation(getClass().getResource("DailySecurityPerformance.fxml"));
System.err.println("loader setLocation passed");
Parent parent = loader.load();
System.err.println("loader.load passed");
Scene scene = new Scene(parent, 975, 600);
5 Posted by Bob B on 07 Aug, 2020 05:34 PM
BTW: the following now works for me to get the css
String css = this.getClass().getResource("/DailyPerformance.css").toExternalForm(); scene.getStylesheets().add(css);
6 Posted by Bob B on 07 Aug, 2020 11:29 PM
UPDATE: hereis what I have tried (all without success). Extension runs in debug but fails in MD direct with :
ava.lang.NoClassDefFoundError: javafx/fxml/FXMLLoader
I've tried replacing javafx 14.0.2.1 with 11.0.2
I tried
String test1 = Scene.class.getPackageName();
System.err.println("test1: " + test1); (that works so javafx is being found)
but
String test1 = FXMLLoader.class.getPackageName() (FAILS)
Anyone have any ideas, I'm an amateur and flummoxed!
Support Staff 7 Posted by Sean Reilly on 07 Aug, 2020 11:34 PM
It seems like FXMLLoader needs access to the classloader, which may not work because moneydance tries to keep extensions from breaking out of their sandbox. If we allow too much access to the class loader then all security is out of the window as any code can be loaded and run within the app.
Unfortunately I'm not familiar with what FXMLLoader is used for, but if you have a stack trace for that exception maybe it might have some useful information?
Thanks,
Sean
8 Posted by Mike Bray (Quot... on 08 Aug, 2020 07:30 AM
Hi Sean and Bob
My take on this is:
The MD class loader (the one that loadss extensions) overrides
getResourceAsStream but not getResource so if you use getResource then
it uses the parent classloader which does not know about .mxt files. I
am assuming that getResource will not find the .css file if it is in the
.mxt file. Hence my code works as it uses getResourceAsStream in the
same way as getIcon in the Main class gets the extension icon.
Sean, I understand the need to isolate the extensions so it does not
interfere with the core code, could the MD class loader be extended to
support more of the classloader methods?
Mike
Support Staff 9 Posted by Sean Reilly on 08 Aug, 2020 08:05 PM
Hi Mike,
Moneydance does override the findResource(String) method in the class loader which is called by the default getResource(String) implementation, so I'm not sure what is missing here. Are there specific methods which don't work, or can you provide a case (and sample extension) when getResource(String) should work but isn't?
Thanks,
Sean
10 Posted by Bob B on 09 Aug, 2020 03:56 AM
Thanks Sean and MIke. This discussion is going a bit (to say the least) over my head. I'n new to this and so I learn by example (thanks Mike for all your examples, they have been invaluable to me when trying to figure this out - particularly the build process).
So my problem is that FXMLoader was not being found - i fixed that part by adding the javafx.fxml.jar into my ant build :
I copied an example from Mike for other jars. I have no idea if this is the correct thing to do, but the FXMLoader Class is now found. But the resource it's looking for (the fxml file) is not found.
The FXML file contains the source for the javafx 'window'. FXML is an XML-based language designed to build the user interface for JavaFX applications. You can use FXML to build an entire Scene or part of a Scene . FXML allows application developers to separate the logic for building the UI from the business logic.
Does that help your understanding?
Mike, you were talking about the css file. Have you managed to get the FXML file to load?
This is the error in the MD errlog.txt
Thanks again for your help. If I can provide any additional information, please let me know.
11 Posted by Mike Bray (Quot... on 09 Aug, 2020 04:53 AM
Hi Sean
I don't have a specific example as I found out early on that getResource does not work. In the quote loader source (which you have) the class ExchangeList loads two files from the .mxt file and I have had to use 'getResourceAsStream' to get it to work.
From what Bob is experiencing I suspect the FX .css problem is more involved. I know that setting the Scene stylesheet does not work. The code I provided does work, but not in debug, which is a problem with Edclipse.
Regards
Mike
12 Posted by hleofxquotes on 10 Aug, 2020 03:32 PM
@ Bob, after you instantiate the FXMLLoader, try to see if you can force it to use the extension classLoader (which in theory knows how to get to your resource in the mxt file).
(https://docs.oracle.com/javase/8/javafx/api/javafx/fxml/FXMLLoader....)
where extClassLoader the extension classLoader. You probably can get extClassLoader from one of the classes that is IN your extension mxt file. Off the top of my head ....
In terms of getting the resource from your mxt file, the ultimate fallback is to do it yourself ;-). You can open the extension file up as a JarFile or use JarClassLoader() and go from there.
13 Posted by Bob B on 10 Aug, 2020 08:58 PM
UPDATE: (are you sick of me yet!)
I create a new simple project. It has a Controller class and a FXML file that displays a label with text. No stylesheet is used at this time.
Once I made sure the FXML file was in the MXT. I was able to get the FXML to load using Mike's technique:
However, I got this error because it couldn't find the Controller class named in the FXML:
So I thought I'd just set the Controller prior to loading and remove it from the FXML file:
BUT now I get this error and I'm stumped again (I've attached the project in case that helps).
14 Posted by hleofxquotes on 11 Aug, 2020 02:24 PM
Couple of places to look for a problem like this:
15 Posted by Bob B on 11 Aug, 2020 05:05 PM
Thanks hleofxquotes for your help. MD does include javafx but it does not seem to include javafx.fxml (at least I get a classNotFound error unless I include in my mxt). I'm not including any other javafx beside that one.
I'm trying to follow your second point but the link talks about add-modules (which I needed to do in Intellij when I configure the debug run environment).
So i did a little further reading and found this: (https://blog.codefx.org/java/five-command-line-options-hack-java-mo...)
If i'm following the discussion (and that a big IF), it sounds like i need to add something to the jvm when running MD. Moneydance has a file: Moneydance.vmoptions that seems to provide the options for the jvm.
I added the --add-opens line but it made no difference. Perhaps I've done it incorrectly.
Sean do you have any ideas, since you know the inner working of MD.
16 Posted by hleofxquotes on 11 Aug, 2020 06:00 PM
I think you have a couple of options depending on what the end goal is
That way all the javafx modules are in the same "module" per se rather than having them mixed.
17 Posted by Bob B on 11 Aug, 2020 09:41 PM
Thanks again hleofxquotes. I feel guilty about you taking this much time to help me. I really do appreciate it.
I did as you said, although I may have misunderstood. I removed the --add-opens and added --module-path and --add-modules
I also tried adding all the javafx modules but still no luck.
I get the same error when running the extension through MD instead of in debugging mode in Intellij.I think using javafx to build a mxt, is not a viable option right now. I'm exploring not using and FXML file and creating the UI and bindings in java classes. I have the UI displaying without styling or bindings so at least I know that works.
Sean if you are still reading this, can you provide any additional info re: support for FXML in javafx extensions.
Support Staff 18 Posted by Sean Reilly on 11 Aug, 2020 10:01 PM
Hi Bob,
I think the best approach would be to tell the FXXMLLoader to use the extension's classloader, so that it has access to the bundled XML through the classloader rather than through the specific input stream.
If your XML is referencing any com.sun classes then I think you might run into trouble, because I'd expect them to be private to the module that contains them.
I've very little experience with javafx, so the above is just a guess based on knowing how the classloaders generally work.
Thanks,
Sean
--
Sean Reilly
Developer, The Infinite Kind
https://infinitekind.com
19 Posted by hleofxquotes on 12 Aug, 2020 01:39 PM
You are welcome.
I think you are very close. I just try using your moneydance-devkit-test.zip file. I made the following change and was able to display the extension window/frame
Not sure which platform you are on but key thing is to check the JVM process and see if it is actually running the above arguments
See attached screenshot.
20 Posted by Bob B on 12 Aug, 2020 11:31 PM
Thanks very much but I think I'm jinxed lol. I did exactly as you demonstrated:
I removed the the reference to javahx from the build file, and checked and made sure they were not in the mxt file.
I modified the moneydance.vmoptions as you did but no variation of entering th data made any difference. The FXMLLoader class is not found.
I tried moving the java fx lb to a different path, I tried the full path name, I tried setting up an environment variable, I tried putting the path on the same line as --module-path ; on a different line (line you) nothing made any difference.
I'm running on Windows and I don't know how to check the JVM process to ensure it is reading the values.
21 Posted by hleofxquotes on 12 Aug, 2020 11:40 PM
Maybe some of these tips can help? https://serverfault.com/questions/323795/display-complete-command-l...
22 Posted by Bob B on 13 Aug, 2020 07:00 PM
I've wmic and while moneydance is listed, there are no command line parameters.
I'm pretty sure the vmoptions file is being read because when I change the entries for memory usage, task manager memory usage climbs.
I've tried to turn on class logging but no log file is ever created anywhere on my system and no existing file is modified anywhere etiher (except errlog.txt from MD but that doesn't have any increased information.
So I'm back to being stumped. there is something odd about how the file vmoptions is used with Windows or maybe there is something the MD does to limit it somehow.
Sean, any insights? With the fact that hleofxquotes can get my little test extension program to run, I have hope that there is something simple I am missing (that may be famous last words).
Support Staff 23 Posted by Sean Reilly on 13 Aug, 2020 08:06 PM
Hi Bob,
I've not been following all the details but have you set the classloader?
loaderFXML.setClassLoader(this.getClass().getClassLoader());
Thanks,
Sean
24 Posted by Bob B on 13 Aug, 2020 11:19 PM
Summary for Sean:
1) Your solution doesn't work because the underlying problem is that I can't instantiate the FXMLLoader class because MD does not include javafx.fxml in the javafx that you ship with. I get the following error in the MD error log (I've highlighted the crux of the matter between \\\ lines):
2) If I include javafx.fxml in the mxt build, that solves the above error but now I get:
3) hleofxquotes has been helpful and suggested I remove it from the build and add the module via the moneydance.vmoptions files as follows (not a solution if I wanted to distribute the extension but good enough for me):He did that to the sample basic simple FX extension that I included in the thread above and was able to get the dialog to display without error (see above) [after he removed javafx.fxml from the build.xml]. He's on unix i think.
4) I tried the same thing (on Windows 10) but it makes no difference. The javafx.fxml is not found. That's where I'm stuck now. I tried many permutations in the vmoptions file for the path but none work.
25 Posted by hleofxquotes on 14 Aug, 2020 03:42 AM
Bob, I started up a Windows VM and am seeing what you are seeing. I do have some pointers for you but I think it will be best to have that discussion via email. Send me email hleofxquotes at gmail dot com.
Support Staff 26 Posted by Sean Reilly on 14 Aug, 2020 06:58 AM
If you wouldn't mind reporting back if you find a solution I'd love to hear about it, and have it here on "on the record" for anyone else searching for the same solution.
Would this all be solved if I simply included the javafx.fxml module in the JRE that's bundled with Moneydance?
Thanks!
Sean
27 Posted by hleofxquotes on 14 Aug, 2020 02:57 PM
Yes, that probably is the best fix.
28 Posted by Bob B on 14 Aug, 2020 04:06 PM
I agree, that would probably fix everything but you might want to test it on the little sample app above. I will post any solution I come up with to help others get going with this. Thanks
Not to get greedy but if you come if a solution to have an external stylesheet for an extension, that would be awesome. Although it's really just a nice to have not that I've figured out how to bundle it inside the extension as a resource.
29 Posted by Bob B on 14 Aug, 2020 05:31 PM
INTERIM WINDOWS SOLUTION (thank you so much hleofxquotes):
Create a bat file and run MD from there as follows - everything needs to be on one line. You will need to adjust the 3 paths in the following to reflect the locations in your setup. This will get you by until a more permanent solution is available from MD.
System closed this discussion on 13 Nov, 2020 05:40 PM.