Scene loads too slow - java

I am building a JavaFX application and I am wondering if there is a recommendation (best practice) on how to load new Scene in current Stage as fast as possible.
Currently what I am doing is (more or less) this:
Parent root = (Parent)myFXLoader.load();
currentStage.setScene(new Scene (root);
The above works fine and fast enough for simple Scenes BUT when loading more complicated scenes that initialize TableViews, Comboboxes etc the transition between Scenes takes many seconds which is annoying.
All the initialization I do in inside the Controller's initialize(URL url, ResourceBundle rb) method.
There I add the items to the Choice/Combo boxes, initialize TableView etc but as I said, it takes too much time.
Am i doing something wrong? Should I initialize somewhere else?
Thank you.
EDIT:
Anyone interested in helping with this, or even get ideas for their project, I have uploaded a part of my project (Netbeans project) at google.com.
You can check it out using SVN. This is the link:
http://tabularasafx.googlecode.com/svn/trunk/
userName: tabularasafx-read-only
no password required
Instructions after you run the project:
First screen is login screen, just click OK
Second screen is "homePage", there you can see a treeView menu and navigate to 4 different screens
My issue is the loading time of classes->create page. Take a look at it and let me know if you find anything
EDIT:
I made 3 changes that #jewelsea suggested.
1. I used a HashMap to keep all the controllers for each screen
2. I update only part of the Scene and not the whole Scene
3. I used the answer of JavaFX2 - very poor performance when adding custom made (fxml)panels to gridpane dynamically to help the controllers load faster as described in the answer.
Everything is much much faster now!!!!
Feel free to use the project as a guideline
Also I update the program to navigate through 3 screens for better understanding
note that my code is a messy

Some Background
I took a look at your project Dimitris.
I timed your load creation time (Java 8 b129 on OS X 10.9, 2012 Macbook Air) for the "classes create" page. It took just over a second for me.
To simplify testing I removed the section where you load new FXML using a concurrent service and just loaded the FXML directly on the JavaFX application thread when it was requested - its a lot easier to work with that way.
Sorry for the long answer here. Things like this usually don't fit well into StackOverflow, they end up best in a tutorial or blog kind of form, but I was curious what was going on, so I thought I'd take some time to look into it and write it up.
Don't create a new Scene for every FXML you load
You set a new scene (with a new size) every time you load the FXML. For whatever reason, this is a pretty expensive operation and you don't need to do it. You already have a scene in your stage, just reuse that. So replace the following code:
stage.setScene(new Scene(service.getValue().getRoot(), service.getValue().getX(), service.getValue().getY()));
with:
stage.getScene().setRoot(service.getValue().getRoot());
This will save just over half a second on the load time, so now classes->create takes about 400 milliseconds the first time it is run.
This change is an example of an easy performance win.
It also provides a nicer user experience as on my machine the stage flashed gray while you were changing scenes, but when you just replace the scene root of an existing scene, there was no gray flash.
Because the JVM runs with a just in time compiler for Java, subsequent requests to display classes->create go faster, so after opening the scene two or three times it takes about 250ms (or quarter of a second).
The FXMLLoader is slow
Of the remaining 250ms to load, about 2ms is spent in your initialization code, another 2ms is spent by JavaFX rendering the controls and the other 246ms are spent by the FXMLLoader loading up the FXML and instantiating the nodes to go into your scene.
The idea with UI code is you want to get the target time for a transition down to < 16 to 30ms. That will make the transition quick and smooth for the user.
Separate your UI code from your Network and Database Code
Network and database calls are things which are best done off of the JavaFX application thread, so you can use the JavaFX concurrency tools to wrap those tasks. But I'd recommend separating concerns. Use concurrent services to fetch data, but once you have the data back, use Platform.runLater or a Task return value to transfer the data the JavaFX application thread and run the population on the JavaFX application thread (because that population task is going to be pretty quick anyway).
This way you have compartmentalized the multithreading in the system to different logical components - networking runs on its own thread and UI operations run on a different thread. It makes stuff easier to reason about and design. Think of it a bit like web programming, where an ajax call fetches data concurrently to the UI, then provides a callback that is invoked to process the data into the UI.
The other reason to do this is that many networking libraries come with their own threading implementations anyway, so you just use that rather than spawning your own threads.
How to make FXML Load Quicker
You shouldn't really need multi-threaded code for loading FXML files. The initialize function of your FXML runs extremely quickly (just a couple of milliseconds). The FXMLLoader takes 250ms. I haven't profiled it in detail to see why that is the case. But there are some indications in Sebastian's answer to JavaFX2 - very poor performance when adding custom made (fxml)panels to gridpane dynamically. I think the main performance issue is that the FXMLLoader relies so heavily on reflection.
So the best solution in situations where a slow FXMLLoader is an issue would be to use some alternative to the FXMLLoader which performs better and doesn't rely on reflection. I believe the JavaFX team are working on a binary equivalent of the FXMLLoader (e.g. the FXML files are pre-parsed in the build stage into binary Java class files which can be quickly loaded into the JVM). But that work (if it exists) is not released by the JavaFX team yet. A similar piece of work has been done by Tom Schindl, which pre-compiles the FXML to Java source, which can then be compiled to Java classes, so again your app is just working with compiled classes, which should be nice and speedy.
So the solutions to make FXML load quicker are currently in the works, but not really stable and usable on a production system. So you need other ways to deal with this issue.
Make your forms simpler
This may seem like a cop-out on my part, but IMO the design you have for your "create classes" scene is a bit complicated. You might want to consider replacing it with a multi-stage wizard. Such a wizard will generally load faster as you only need to load a handful of items on each wizard screen. But the more important point is that such a wizard is probably easier to use and a better design for your users.
Replace only the sections of your scene that you need to
You are loading FXML files which create your whole application UI for each new page. But you don't need to do this because things like the top menu, status bar and navigation sidebar don't change just because the user loads a new form - only the central section where the "create classes" form is displayed is changing. So just load up the nodes for the part of the scene that is changing rather than the entire scene contents.
Additionally this will help fix other issues that you will have with your application by replacing the whole UI at each stage. When you replace the navigation menu, the menu doesn't automatically remember and highlight the currently selected item in the navigation tree - you have to go and explicitly remember it and reset it again after doing a navigation. But if you weren't replacing the whole scene contents, the navigation menu would remember what was last selected and display it (because the navigation menu itself isn't changing on navigation).
Cache FXML load node trees and controllers
You are only ever displaying a single "create classes" form at a time within the application. So you only need to use the FXMLLoader to load the "create classes" form once. That will create a tree of nodes for the form. Define a static HashMap that maps "create classes" to the CreateClassesController object (of which you also have only one in the application). When you navigate to the "create classes" screen, see if you have already been there before, by retrieving the controller from your hash map. If there is already an existing controller class, query it to get the root pane for form and display the form in your scene by replacing the center panel of your scene with the new form. You can add extra methods on the controller that you can call to clear any existing data values in the form or to set any data values which you have loaded from a network fetching task.
In addition to speeding up your application, you now have the advantage that the state of the "create classes" form is kept until you or the user decide to clear it. This means that the user can go through and partially fill out the form go somewhere else in the application then return to the form and it will be in the same state as they left it rather than forgetting everything the user entered before.
Now because you load the "create classes" form only once, you could load up all of the forms at startup (and have a preloader page which indicates that your application is initializing). This means that initial startup of the app will be slower, but operation of the app will be quick.
Suggested Design
Create forms for different panel sections in your app (nav bar, "create class" form, "home screen", etc).
Create and manipulate UI elements only on the JavaFX UI thread.
Only replace panel sections on navigation, not entire scenes.
Precompile FXML to class files.
Use a Splash Screen pre-loader if necessary.
Abstract networking and data fetching code into its own thread.
Reuse cached node trees created for panel forms rather than recreating them.
When new network data is available, transfer it to the UI thread and fill it into a cached node tree.
Review the SceneBuilder Implementation
Follow the principles used the SceneBuilder implementation itself - it is the best current design example for a reasonably sized JavaFX project that makes use of FXML for its UI. The SceneBuilder code is open source and distributed under a BSD style license, so its good to study.
Outcome
I prototyped some of the ideas mentioned in this answer and this cut the initial load time of the "create classes" screen down from over a second to about 400ms (for the first time the screen is loaded). I didn't replace the FXMLLoader with something else, (which I am sure would have greatly decreased the 400ms value). Subsequent loads of the "create classes" form based a cached node tree that was just re-added to the scene took about 4ms - so operational performance was instantaneous as far as the user was concerned.
Update for Additional Questions
Do you think that I should use Tom Schindl's solution for compiling FXML or is it "too Beta"?
My guess is that (as of today) it is "too Beta". But try it out for yourself and see if it meets your needs. For support on the Tom's FXML => JavaFX compiler, post to the e(fx)clipse forums, as the project falls under the larger umbrella of the e(fx)clipse project.
And I tried 'stage.getScene().setRoot(service.getValue().getRoot());' but got OutOfMemoryError: Java heap space do you think that line caused it or it is not relevant?
I was doing some profiling of your code as part of creating this answer (by attaching the NetBeans profiler to an already running instance of your application). I did notice that every time the "create class" scene was loaded by your program, the memory usage would grow quite significantly and the memory did not seem to be released. I didn't spend time trying to track down what the reason for that was, but that was profiling your code unmodified. So I suspect that the ultimate cause of the system running out of memory is not to do with whether you swap out a scene or just swap out a scene root. I noticed a lot of memory was consumed by CSS psuedo-classes, though I couldn't tell you the reason for that. My guess is that if you follow the principles outlined in this answer, then overall, your application will be a lot more efficient and you may circumvent the memory related issues present in your current code. If not, you could continue to profile the application memory usage to see what the root issues are.

the speed of the scenes are going to have a lot to do with how many object you are trying to initialize in the scene right from the beginning. So if you can lower that number to the minimum and create the rest while the scene is running everything will run a lot smoother. If that is impossible in your situation maybe just try limiting other things to reduce the strain on the system.

If you are using scene builder, then run it as administrator externally (not from the ide side).
Problem will be solved.

Related

Java FX Multiple Windows App

How are big applications (with lots of windows, lets say users administration, roles, payments, etc) designed. I'm a web developer and I'm used to develop different screens in different html files. I wanna know how to split windows generations in different files instead of having only one huge Application class.
Thanks in advance..
The question is a bit too broad to thoroughly answer, but I still think providing a partial answer here might be useful.
For an implementation of Banislav's strategy of hyperlinks controlling a swappable pane (which does not use FXML), see the related question: How to have menus in java desktop application.
For a small FXML based framework for switching panes see: Loading new fxml in the same scene with associated sample code. Note that sample is for small apps, for large apps a more rigorous framework would be preferred.
The next step up from the small framework listed above would be something like afterburner.fx, which is "a minimalistic (3 classes) JavaFX MVP framework". Even though small, afterburner.fx would probably suffice to be used as the core for a medium sized application. You can find a small sample application built using afterburner.fx named airhacks-control.
For something a bit more involved you can study the source of SceneBuilder and SceneBuilderKit. SceneBuilder is an open source design tool written in JavaFX. Understanding and adapting that code may be challenging for somebody coming from a web background as its implementation differs significantly from a traditional web application.
For very large applications, basing the application on a fully featured platform such as NetBeans RCP would probably be a preferred approach, though, as of this time, that is probably a large and difficult task to do well and likely requires mixing multiple frameworks rather than writing everything purely in JavaFX.
In JavaFX, you can use similar approach as in web development.
Use BorderPane as root pane.
Create main menu
You can use MenuBar with Menus and MenuItems. You can also use TreeView or ListView on like left side of screen. To position TreeView/ListView on left side you could use BorderPane and set it to left with setLeft.
Approach I prefer would be to use HyperLink control. Add multiple HyperLink's to VBox and again, set them on left side of BorderPane. Upon click, they will handle event which set's desired form on center of BorderPane.
I.e.

How can I make it so Eclipse automatically updates my code in a window as I edit it?

How can I make it so Eclipse automatically updates my code in a window as I edit it? I've seen the feature before in youtube videos but I cannot find it. For example : I change a JApplet rectangle width from 20 to 10, I want to see it update immediately.
I've seen Notch do this on development videos (Minecraft), it is awesome but I don't know exactly how he does it.
-- EDIT --
This has been bugging me so I went and googled "how does notch code" and found this on a blog page https://gun.io/blog/what-i-learned-from-watching-notch-code/. It doesn't say exactly how it was done but gives a good hint (HotSwap) and makes it seem like he set it up himself without external software. Here's the most relevant section:
Incredibly Fast Testing
He began by building the engine, and to do this he used the ‘HotSwap’ functionality of the Java JVM 1.4.2, which continuously updates the running code when it detects that a class has changed.
When building the engine, Notch wrote a function which would continuously pan the camera around and clip through the walls and keep the view on top, so he could make changes to the code and see the effects they made in real time. I’m used to testing by writing a function, building it, installing it on the device I’m testing on, and then seeing the result, which can take up to a minute at a time, so it’s easy to see how HotSwapping could save a lot of development time.
--- ORIGINAL POST CONTINUED ---
I get a similar effect by using groovysh though, works smoothly and can use all your java classes as is.
What I'll usually do is write all my code in java, then go and fire up "Groovysh" where it will give you a little window to enter commands (You may have to ensure the classpath works correctly outside of eclipse). I can then "new" any of my classes and call methods on them one line at a time. When you do myFrame.setSize([100,100]) you will see it change immediately.
A good test is to just run groovysh and type something like:
import javax.swing.*
f=new JFrame()
f.setVisible(true)
f.setSize(100,100)
or the groovier version:
f=new JFrame(visible:true, size:[100,100])
and you will see your frame resize on the screen. You can even drag it bigger and then do something like:
println f.getWidth()
to show your new width. It's fun to interact this way but it's more complicated if you want to actually change your class definition and see it pick up the change, I have no idea how Notch did that. I looked into it a little--it's possible he was using something like JRebel
It requires something special since you would have to dynamically reload the classfile into your running system on every save--something that should have serious classloader issues.
By the way there is also a way to get your Java program to throw out a little GroovyConsole which will allow you to inspect and modify all the variables in your running code (but again you can't replace definitions of existing classes).
Also see answer here:
Change a method at runtime via a hot swap mechanism

Is capturing screen image and displaying it on an application every second effective?

I'm new to programming but I really wish to improve, right now learning Java. Basically there is this game, online strategy it's pretty basic with most of the images are static and very few of them change. I wish to change how I view the game from my end and add some functionality to it as well.
For example the website displays an orange rectangle, I wish to display a red rectangle by drawing over it. Or drawing a button when, if clicked, re-directs me to another part of the game. Originally I am using Selenium Chrome WebDriver to navigate the website but it seems you can't paint or display your own images over it. So I was wondering if I should use Selenium headless in the background performing tasks while I just make a Java Application. Make the WebDriver capture the image every second and display it on the Java Application every second, and than edit that image to my liking? Would this be effective way to do it or is there better options?
It is not clear what you are actually trying to achieve here. And whether your approach is likely to be "effective" depends what you are trying to achieve!
However, I can see some issues:
I don't know if it is technically possible to get the Selenium WebDriver to do that ...
Capturing images at a high rate could be problematic from a performance perspective.
Once you have captured the images:
Modifying the images by hand would be tedious and labour intensive. (And probably not what you want to do.)
Modifying static images programatically would be possible, but fiddly to implement and incredibly fragile. The slightest change to the game's screen rendering could result in your "tweaks" writing to the wrong place on the image.
Making changes to the dynamic part of images would be next to impossible ... except in the destructive sense.
You can't affect game play by this approach. Nothing you do to the images will impact on the browser and hence on the server. You can't add functionality this way.
In short, this is a poor idea, and unlikely to achieve anything worthwhile.
Can I think of any good options? No I can't.
The best I can think of would be to:
reverse engineer the HTML / Javascript uploaded to your browser,
figure out what you want to change in that content, and
place an HTTP proxy between your web browser and the server that injects the relevant changes into the content.
However:
It will be a lot of tricky and tedious work to implement.
It will be fragile; i.e. changes to the game / game server are liable to break your "hacks".
It could be a violation of the game owner's copyright and/or the license that grants you the right to use the game. This could result in your game accounts being cancelled, along with the accounts of anyone else who uses your "hacks".
My advice? Just play the game!

Getting a clue at / debug a huge Java Swing App I've inherited

I've been given the task to implement a new end-user functionality into a Java/Swing application. The task to implement is relatively easy and straightforward. What is cumbersome is the existing app to be modified.
It comprises dozens of classes which often break the 2000 lines barrer and sometimes reach 10000 lines.
Documentation is non existent and it is unfeasible to read all the source code to get the big picture of it.
The app itself is basically a GUI tool to draw diagrams (e.g. flowcharts) and is open-source (I can post the link to the source code if it helps).
So far I've managed to import the source code into an Eclipse project and use the SwingExplorer plugin to identify some of the GUI components.
The most 'interesting' part of the app is the canvas onto which the diagram is drawn. It is implemented as a single class (about 9700 lines long) that inherits from JComponent.
The parts of the displayed diagram can't be selected in SwingExplorer: the whole canvas is only identified as a single instance of the aforementioned class.
I hence guess that this huge single class is taking care of all the user interactions and AWT drawing operations for the diagram and returning just some kind of image buffer to display (but this is a huge guess).
My modification involves doing computation on the diagram as it is being drawn on the canvas. Therefore it is going to be a new class which will receive and process events broadcast during the creation of specific elements of the diagram, and then do some computation on them.
My main problem is: how to debug the event flow? How can I follow the flow of execution when drawing a diagram and see which events are generated, processed and also get an idea of where in memory the objects being drawn reside?
I know this question might seem too generic, but I'm really clueless and looking for a starting point.
Thanks in advance only for taking the time to read through ;)
Regards,
Marco
In NetBeans, I use File > New Project > Java Project with Existing Sources to allow easy navigation. Most IDEs have a similar feature.
Use Run > Generate Javadoc; even without comments, the Overview, Index, Use and Tree links may be useful.
Set breakpoints in the debugger and use Window > Debugging > Call Stack to answer question like, "How did I get here.
Run the code in the integrated Profile > Profile Project mode to see principle execution threads.

Converting an AWT application to SWT/JFace

I am currently toying with the idea of converting a small/medium sized project from AWT to SWT, although Swing is not totally out of the picture yet.
I was thinking about converting the main window to an SWT_AWT bridge object, but I have no idea how the semantics for this work. After that, I plan to update dialog for dialog, but not necessarily within one release. Is this possible?
Has someone done a conversion like this and can give me some hints? Is there maybe even a tutorial somewhere out there? Is there maybe even a tool that can automate parts of this? I have tried googling, but to no avail.
Update: One additional thing is: Currently, this is a netbeans project. Might be of help or not, I don't know.
We have done this quite a few times. But only because we are going from a Swing application to an Eclipse RCP application not because we like messing with things. This project will really let you know whether you've separated your controller/model code from your view code.
One suggestion is to not try and convert everything all at once. You will end up with a bunch of mixed code that doesn't work at all. You can start at converting portals. I would consider a portal anything within a Tab, Dialog, or Window, essentially self contained unit. If you have a window that opens up, create the Window in SWT, but make it's contents the existing AWT/Swing. This should be fairly straight forward and allow you to get used to the (I really hope they weren't drunk and had a good reason for this) way of instantiating and associating parent/child controls.
One gotcha that can occur is with transparent components. Swing, with the exception of a "window" class is all rendered in Java. This makes it very easy to render things the way you want them. In SWT, there are some restrictions:
Borders. If you use SWT.BORDER you are stuck with whatever color the native component uses. Your best bet is to use a PaintListener and render your own borders if you want them in a different style or color.
Transparent labels, progress bars. I have not been able to get Labels or Progress Bars to have a transparent background. If you want them to take on the parent color, or drawing you will need to render the text and other controls yourself.
Controls. There are composites and controls in SWT. Think of Controls as the basic native controls that do all the native API calls. These cannot be subclassed, which makes things difficult.
Tables will give you the most trouble. Make sure everything is stable before you attempt to convert a JTable to a Table or TableViewer. You will spend some time on these, especially if you have custom editors and viewers.
I have not researched why SWT was designed the way it was. I am guessing there HAD to be a good reason. It would be great if someone had a blog or defense to it's design so I don't have to search for it. Once it's posted I'll remove these lines since they have no relevance to the question.
Addition
I want to add that since you have an existing product I assume works. The best piece of advice I can give you is to never let your code get into a state that it cannot compile and run. If you work on your conversion and whatever you check in always runs and executes (despite the visual differences between SWT/AWT/Swing) you will save yourself many headaches in the long run. The worst thing you can do is try to tackle this all at once and get your code in an unstable state for weeks at a time.
I would suggest importing it into a WindowBuilder project, as WindowBuilder gives you the ability to parse existing code and create a GUI mock-up, then morph components to either SWT or Swing.
If you're thinking of using a mix of SWT and Swing in the same application, this Eclipse Corner Article will be immensely useful.
We are preparing the same step: Swing to SWT/JFace. First we try to determine the bottlenecks: reimplement special components derived from JComponent with SWT/JFace, search for a replacement of JIDE docking (we want to use SWT/JFace, not RCP to avoid too much hassle). The worst thing we already imagine is, that in Swing you could create components and adding it later to the parent. With SWT this is not possible: the parent component must be passed as a reference to the child component's constructor. This will require major refactoring in the Swing application before using SWT.
Frankly, we rate the conversion a very heavy change, because we expect the time where nothing can be compiled as quite long. We try to decrease this time by preparing everything as good as possible, but we'll see how good it will work.
Update from April 6th 2011:
We now refactored our Swing application to always create components with their parent (as in SWT). Our subclasses of JFrame and JDialog got refactored to just have a JDialog instance to make it easier to switch to SWT's Shell. In parallel, we rewrite sophisticated components in SWT.

Categories

Resources