Granny's Programming Pearls
"inside of every large program is a small program struggling to get out"
JavaRanch.com/granny.jsp

John Damien Smith

Ranch Hand
+ Follow
since Jan 26, 2012
Cows and Likes
Cows
Total received
27
In last 30 days
3
Total given
0
Likes
Total received
101
Received in last 30 days
6
Total given
31
Given in last 30 days
1
Forums and Threads
Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by John Damien Smith

The problem is not that the text area is not initialized, the problem is that it is explicitly set to null:

You should never set members which have been annotated @FXML to anything.  
The FXML controller will instantiate the appropriate component based upon the corresponding `fx:id` attributed element in the FXML and automatically associate the instantiated component with the @FXML annotated reference in the class.
I'm not sure if that will cause the null assigned txaSessionLog to be set with the correct value or if it will mean that the variable is first assigned the correct value and then overwritten to null.  Regardless it is confusing, so removing the "= null" from the declaration is preferred.
There could be other problems too, I didn't check.
2 days ago
I haven't used JDK 12.  These kind of module errors don't occur in JDK 8 as that does not have modules, but that is old and outdated so it is better to get the modular system in JDK 12 to work.

Take a look at:
https://stackoverflow.com/questions/54291958/javafx-11-illegalaccesserror-when-creating-label
There is says:
"you need to set the required VM options for your project"

I haven't got a copy of JDK 12 locally to try it at the moment, but you could try giving it a go.
1 week ago
> instructions on downloading a version of SceneBuilder that has a specific "internal version"

The only distributions I know of are the two currently provided by Gluon:
 https://gluonhq.com/products/scene-builder/
There is currently one for Java 11 and another one for Java 8, though this will change with time.
So, no, there won't be one which runs on exactly the same version of the Java platform you are currently developing on.

> how to patch the installation we already have.

Don't try that, it would not be recommended.
2 weeks ago
On Intellij Idea, you can choose Code | Generate (command+N on Mac) and it can will generate different pieces of code for you like getters/setters, equals and hashcode.  
The generation is JavaFX property aware.

So, if you have:

Then you press command+N on a Mac and choose Generate | Getter and Setter, you get:

There are a bunch of design patterns in the JavaFX property cookbook (worth reading if you haven't seen it, though some of them are slightly outdated, e.g. does not make use of things like ReadOnlyIntegerWrapper for a read only property):
https://wiki.openjdk.java.net/display/OpenJFX/JavaFX+Property+Architecture
They demonstrate some subtlety, especially around things like lazy initialization and read only properties, that aren't provided directly in the generated property code from the IDEs.  For instance, an IDE (at least Idea) won't generate code such as that below for a read only wrapper:

Still, Lombok won't create the appropriate property accessors for JavaFX properties as far as I know.  

So, what I'd recommend for JavaFX development which has a lot of properties, is to just use an IDE, use the quick code generation functions of the IDE to generate some boilerplate code for getters/setters, etc as needed, then examine the generated code and modify it as required to fit the exact accessors and patterns you need for your app (if you use things like read only properties - which you should because reducing the mutability of code makes it easier to understand and debug).
 
2 weeks ago
> JavaFX API == jre/jdk version?

Yes for versions of JRE/JDK/JavaFX that are older (e.g. 8 or 9).
Not necessarily for versions of JRE/JDK/JavaFX that are newer (e.g. 11).
This is because for newer Java versions they have been separated from the JDK/JRE and are available as a separate library (like many other 3rd party libraries available for the Java system) and hence the JavaFX system based upon a library can have a different version number than the JRE/JDK it is running on.

> How would I go about setting up a situation where when I edit a file in Scene Builder, it does so against a JavaFX API version that matches the jre I am running in?

I don't know that you necessarily need to do this, it will usually be OK for those things to differ, though you may get warnings if the Scene Builder is running a later version of Java than what your target runtime is.

In such a situation, to be absolutely sure, you need control of the JRE which the app will run on.  You could package the application as a self-contained application (which is a natively installed application with its own embedded JRE) to do this.  Such packaging is likely not 100% trivial, though there are tools and guides on how to accomplish it.  This blog post might assist:
 https://medium.com/@adam_carroll/java-packager-with-jdk11-31b3d620f4a8

Without an embedded JRE, you may wish to check yourself for some other way to ensure that the JRE version is compatible with your app.  Probably, you could run a check on startup to see if the Java version is less than or equal to whatever Java version was used to create the app in Scene Builder or some other tool, and handle things as gracefully as you wish if you detect a conflict.  An exact match is probably not necessary as Java is largely backwards compatible (except when major rework has been done such as moving the JavaFX code out of the JRE and into a library).

I'd recommend using a more modern version of both the runtime and development tools, e.g. https://openjfx.io currently distributes Java 12 and Gluon currently distributes SceneBuilder v11 https://gluonhq.com/products/scene-builder/

> scene builder seems to have come with some arbitrary version of, I'm guessing, JavaFX?

I think scene builder itself is packaged as a "self-contained application" as I described above.  So it includes its own runtime for both Java and JavaFX, using whatever internal version that distribution of SceneBuilder was built to run against.  So it doesn't matter what other JRE version you may have installed on that development machine (at least as far as SceneBuilder goes), because SceneBuilder only uses the JRE that is embedded in its distribution.
2 weeks ago
You can listen to the iconified property and if it gets set to true, set it back to false again:
 https://openjfx.io/javadoc/12/javafx.graphics/javafx/stage/Stage.html#iconifiedProperty

You could also listen to changes to the windowHiding property and do something if it changes.
 https://openjfx.io/javadoc/12/javafx.graphics/javafx/stage/Window.html#onHidingProperty

You could also adding an event filter to the stage for the WINDOW_HIDING event and consuming it if it arrives (that may or may not do what you want, I haven't tried it).
 https://openjfx.io/javadoc/12/javafx.graphics/javafx/stage/WindowEvent.html#WINDOW_HIDING
 https://docs.oracle.com/javase/8/javafx/events-tutorial/filters.htm#BCFDCCEJ

Or you could put the window in full screen mode, which may or may not be what you want).
 https://openjfx.io/javadoc/12/javafx.graphics/javafx/stage/Stage.html#setFullScreen(boolean)

> I'm using LinuxMint, and UTILITY doesn't work very well, the minimize some button, but the maximize button doesn't.

Could be a limitation of the windowing system in LinuxMint rather than JavaFX then as this seems to work fine on OS X.

> there are millions of people on the net looking for how to do but no one has the solution.

It is unlikely that there are millions of people looking to do this :-)
2 weeks ago
Use StageStyle.UTILITY "Defines a Stage style with a solid white background and minimal platform decorations used for a utility window."
https://openjfx.io/javadoc/12/javafx.graphics/javafx/stage/StageStyle.html#UTILITY

On OS X this displays as a window with a title bar, close icon, resizable borders and no other decorations.
2 weeks ago
> Is it possible to upgrade JavaFX without upgrading the SDK, or are they linked at that level?

For Java 8 and 9 the JavaFX system is part of the JRE, so, no, for those versions, you can't upgrade JavaFX without also upgrading the JRE.
For later versions based upon the versions distributed at https://openjfx.io the JavaFX system is distributed as a distinct set of libraries and modules from the JRE, so they are not as tightly entwined.  Whether for openjfx it is possible to upgrade JavaFX independent of the JRE (and vice versa), I don't know, but I wouldn't be surprised if that is possible.

> I'm assuming were talking about upgrading from 8.0.112 to 8.0.<latest>

No Java 8 is quite old now and (as far as I can tell, only on long term support, so that it gets fixes for major security issues, but not other bug fixes).
I was talking about trying the most recent version of openjfx (openjfx 12 on openjdk JRE 12). If any bug fixes for your issue were done over the years (assuming it is a bug in JavaFX that needed to be fixed, which it might not be), then the fixes should show up in the latest version of the code.
2 weeks ago
> Not sure what you mean by "scene graph".

See the following articles to see what the scene graph is:

* https://docs.oracle.com/javafx/2/architecture/jfxpub-architecture.htm#A1106328
* https://docs.oracle.com/javafx/2/scenegraph/jfxpub-scenegraph.htm

Basically, if a node is in an active scene graph, i.e. attached to a displayed window or a scene you try to snapshot, then you can't set or query any of the properties of any the node which is attached to the scene graph, or change the structure of the scene graph by adding or removing nodes.

> Is there a way where we can do something wrong in this area and not see it right away?

Yes, when you modify or query a value off of the JavaFX application thread, then there is no guarantee that an exception will be thrown which you can handle, indeed it may just break the app in an unpredictable way due to a phenomenon known as a race condition:
 https://en.wikipedia.org/wiki/Race_condition#Example
Sometimes the JavaFX system is sophisticated enough to detect some sources of potential race conditions and raise exceptions before they occur, other times it is not, and some unexpected error just occurs.

I couldn't tell you if you have a race condition in your code, but it is one possible cause of exceptions like the one you logged.  In my experience, unless there is a coding error in the underlying JavaFX framework, a race condition is the most likely cause of issues similar to what you are observing.

One reason why I asked if the stack trace is always the same, is that sometimes when you have a race condition, an error can manifest itself in different ways, seeming somewhat random and the exact location where the exception occurs can change depending upon when data was concurrently modified or viewed by different threads.

> Javafx.runtime.version=8.0.112

If the problem is actually an internal error in JavaFX, and not in your code, then you could try upgrading to a later version of JavaFX and seeing if it fixes the issue (because a bug fix which occurred sometime in the last few years might have fixed the cause of the issue).
2 weeks ago
Is the stack trace always the same, or does it differ sometimes?

What is the exact version of JavaFX you are using?
(so that somebody could analyze the stack trace against the JavaFX source code to see what source the line numbers correspond to).

Are you doing any work at all off of the JavaFX thread, and modifying or reading anything to do with the scene graph from the other thread?
(which can cause race conditions which can lead to unexpected exceptions occurring).
See the stack overflow question linked below to understand what kind of issues may arise from doing things like this and how to prevent them:
 https://stackoverflow.com/questions/38770112/javafx-changing-text-area-in-javafx-concurrent-task
3 weeks ago
The accessor for your properties in your ObservableIdPair should not have get in front of it, otherwise PropertyValueFactory won't pick it up.  
You should to follow established naming conventions, not just for readability purposes, but also so automatic introspection code works.  
However that isn't really your issue because you have a standard getter (e.g. getName()), and that PropertyValueFactory can fall back to get the value from that.

NOT:


INSTEAD:


You have code like this:


Never should you set a value initialized by FXML to a new value.  Instead work with the existing value which is injected by FXML.  What the code you have will do, is add additional new columns to the columns in the table which were already added by the FXML, which really isn't what you want.

There are lots of other issues with your code.  For example, you should never have @FXML injected variables in an Application class.  FXML will generate a new controller, but you can only have one instance of an Application class and that is generated by the JavaFX system at startup.

Your FXML should reference your controller class (use an fx:controller attribute on the root container to do this).  You should actually have a separate class which is the controller class and has the @FXML annotations in it.  The initialize method in the controller should initialize the UI.  As all of then UI items you need are already defined in the FXML, you do not (and should not), create new versions of them anywhere (FXML will create instances of all the UI items you need).  All you need to do is to wire the UI controls to your data.  For your table, the small snippet of code below in the initialize method of the controller is the only thing that is needed to put data in the table:



In terms of Architecture, with your Browser interface, the JavaFX application class should not extend that.  You should follow a single responsibility principle of design.  The application class should only be responsible for launching the app, loading the initial stage and cleaning up resources on shutdown and nothing else (i.e. even in the final production version of the code, there wouldn't much else you would want to put in there other than perhaps starting up or shutting down a database connection pool if that is needed).  Your controller class should probably just deal only with the UI elements and not the full functionality of whatever your Browser interface is, then you should have a BrowserService or BrowserImpl in another class which extends from the Browser interface and implements whatever that thing is supposed to do.  Perhaps the Browser Interface itself should be split across multiple functions, such as a LoginService or SessionService, DatabaseConnectionService, DAO objects or other things like that, but I don't know enough about what you are trying to accomplish to really know about that.  To tie browser implementation and the UI controller together, you could either set the browser service instance into the controller https://stackoverflow.com/questions/14187963/passing-parameters-javafx-fxml or get the controller from the fxml loader and set that into the browser service and have that directly manipulate the UI elements in the controller (if you wanted a really tight coupling between the BrowserService implementation and the BrowserController).  So, there are lots of architectural choices and discussing them all in detail is above the scope of what I would be prepared to do here.

Anyway, what I did, which may or may not help you, but at least creates a running app from which you can start to rework your implementation if you wish to, was take some of the code you have, reorganize it according to some of the conventions, corrections and principles mentioned above by Knute or myself, chop out of bunch of stuff which seems irrelevant to the current problem at hand, and create a working version of it which loads an updated version of your fxml file, wires some dummy data into it, then displays it.  

After doing this, the FXML renders fine, the controller is initialized and the sample data (name "Rincewind", id "42") displays fine in the resultant table.

ems.FXBrowserApp


ems.FXBrowserController


ems.ObservableIdPair


ems/EMSInterface.fxml
3 weeks ago
Let's go back to the original thing you are trying to do:

"I was trying to make a TableView that retrieves data from an mySQL server, and displays it."

Here is an example from StackOverflow, I just copy and pasted the code here (it is not my work):
https://stackoverflow.com/questions/25651641/javafx-mysql-connection-example-please

Also, if your actual problem is only on how to render stuff in a TableView and not the related SQL stuff, then it is even easier (adding database interactivity always adds more overhead to a question and makes it harder for somebody trying to the answer to reproduce the issue), so, in the future, when asking a question, just narrow it down to only the thing which is the actual issue, as that may help you get a relevant answer quicker.

I advise trying to get the example from StackOverflow working correctly in your environment, then, once that works, compare its implementation to your code to work out what went wrong with it (or just rewrite your code based upon your new understanding of how this stuff works).

You would write a Person class:



A class to access the data from the database:



And then a UI class:

3 weeks ago
You want to configure a column resize policy for the table.

See: https://stackoverflow.com/questions/11484960/table-column-wont-take-full-size-of-the-table-view-in-javafx
1 year ago
There is an additional example of highlighting cells in a table based upon a boolean cell value over on StackOverflow:
 https://stackoverflow.com/questions/16200901/background-with-2-colors-in-javafx
Note, that is for a specific cell, but from your question, you want to highlight entire rows, in which case the following StackOverflow question might be more appropriate:
 https://stackoverflow.com/questions/32119277/colouring-table-row-in-javafx
The trick from there, which I just copy here, is to use a row factory:
1 year ago