I'm quite new to JavaFX and Java in general, but I've experienced something weird. At first, I took a Java course and there we were creating layout for application using SceneBuilder. I've finished the course and I'm trying to write some simple applications on my own. But whenever I look for some solutions for problems on the Internet, everywhere layout is implemented in code, that means: using something like this:
Label secondLabel = new Label("I'm a Label on new Window");
StackPane secondaryLayout = new StackPane();
secondaryLayout.getChildren().add(secondLabel);
So my question is: how I should create layout? Should I stick to the SceneBuilder or code it in Java as apparently everyone does?
Use the right tool for the right job
There are benefits for using both approaches and you cannot tell in general which one is better without analyzing the scene you're trying to create
Pros of FXML
Fast to design
WYSYWYG Editor(SceneBuilder)
Scenes can be modified without the need to recompile the app
Nice seperation of view and controller with injection
In most cases fxml structure resembles the object structure closely making it easy to read.
Cons (compared to java code)
loading a fxml is slower than java code
no loops possible. When you need to insert something 10 times into a scene you need at least 10 tags; you have to insert the thing 100 times? Thats at least 100 tags. A single tag may not even suffice, e.g. for a GridPane there is no way to insert multiple nodes to multiple columns per <fx:include> tag.
Storing nodes into a collection requires assiging different fx:ids to all the elements and then listing all of them at a different location.
No compile-time checks. You want to add a Integer to the child list of a parent? You can write a fxml that attemts to do that without getting an error - that is until you attempt to load it. The java compiler would immediately complain about something like that.
There is just no way to invoke some methods from fxml.
Loading fxmls relies on reflection
You can of course use java code in the controller class which allows you to combine fxml+java code to a certain level. E.g. repetetive structures could be created in the initialize() method.
Scene builder is amazing when you are building project with JavaFX+FXML,i cant recommend it enough.
When you use fxml your classes become so much cleaner, and you can focus on further extending functionality of your containers/controls.You are still gonna be using javafx classes and your controllers might become quite big. Its good to know the concepts of how to structure layout and when to use what kind of container, so when you just started to learn basics, implement your layout in code, and then move to using SceneBuilder and FXML.
Once you implement more complex layouts in your code, you can translate these skills into other languages/platforms.
There are also cases where you cant do what you want via SceneBuilder, for instance some dynamic layout thats beign created at runtime and would be too tricky and messy to include into separated custom components/fxml files. Then you write it down in your code with complex logic on top of it.
Implement it using SceneBuilder/FXML directly. JavaFX was designed to use XML UI definition files instead of programming your UI in Java code. It is a separation like in Android.
Related
I am attempting a study of JavaFX because I want to use it as the GUI of my program. My question is essentially a conceptual one:
To date my program is mostly the "Model" part of the MVC pattern; that is, almost all of my code is the OO-representation of abstractions in the sense of classes, and all of that code is logical code.
Since I do not want to be the only user of my program, I want to add the "View" part of MVC so that people can easily use and manipulate the "Model" part of my program. For this, I want to use JavaFX.
In my "Model" classes I obviously use various Lists, Maps, and other classes from the Java Collections API. In order to let the users of my program manipulate these underlying Lists and Maps I want to use the Observable(List/Map) interfaces in JavaFX.
A concrete example to bring clarity to the situation:
Let's say that I have a MachineMonitor class that every 3 minutes checks certain properties of a Machine, such as if the connection is still good, the speed that the gears are turning, etc. If certain inequalities are met (say that the speed of the gears has fallen to a rate of 1 turn/sec) the MachineMonitor fires a RestartMachineEvent.
Currently I use an ArrayList<MachineMonitor> to keep track of all of the individual MachineMonitor's. Now extending to the "View" part of MVC, I want the User to be able to manipulate a TableView that displays the list of MachineMonitors so that they can, for instance, create and remove new MachineMonitor's to monitor various Machines.
So that I can keep track of what the user of my program wants to do (say, create a MachineMonitor for Machine #5 that checks to see if the turn/sec of the gears falls below 0.5) I use an ObservableList<MachineMonitor> as the underlying List for the TableView.
The easiest way to link the "Model" and "View" of my program would simply be to change the "Model" class to have an ObservableList<MachineMonitor> and not an ArrayList<MachineMonitor> but (getting to the topic of the question) I feel that this is very messy because it mixes "Model" and "View" code.
A naïve approach would be to use an ObservableList<MachineMonitor> for the TableView and retain the use of my ArrayList<MachineMonitor>. However, changes made to the ObservableList<MachineMonitor> do not affect the underlying List as per the JavaFX specifications.
Given this, is the best way to solve this conundrum to make a ChangeListener for the ObservableList<MachineMonitor> that "propagates" the changes made to the ObservableList<MachineMonitor> to the underlying "Model" ArrayList<MachineMonitor>? Perhaps put this in a class called MachineMonitorController?
This ad-hoc solution seems very messy and non-ideal.
My question is: What is the best way to retain nearly complete separation between the "Model" and "View" in this scenario?
Briefly, I don't think use of ObservableList breaks the MVC contract.
The rest, you may read or not as you wish, as it is quite annoyingly long.
Architectural Pattern Background
Observables are useful in MVC style architectures because they provide a way of feeding data back and forth between the MVC components through loose couplings where the model and view classes don't need to refer directly to each other, but can instead work with some shared data model which communicates data flow. It's not a coincidence that the Observable pattern and the MVC style architecture concept both originated around the same time at Xerox PARC - the things are linked.
As noted in Martin Fowler's GUI architectures, there are numerous different approaches to building GUIs. MVC is just one of these, kind of the granddaddy of them all. It is nice to understand MVC well (it is often misunderstood) and MVC concepts are applicable in many places. For your application you should use the system which feels best for you rather than rigidly following a given pattern (unless you are using a particular framework which enforces a given pattern) and also be open to adopting different patterns within an application rather than trying to shoehorn everything into a single conceptual framework.
Java Beans are a fundamental part of almost all Java programs. Though traditionally often only used in client apps, the observer pattern, through PropertyChangeListeners, has been, for good reason, a part of the Java Bean specification since it was created. The observable and binding elements of JavaFX are a rework of that earlier work, learning from it to build something that is both more convenient to work with and easier to understand. Perhaps, if the JavaFX observable and binding elements had existed ten or twelve years ago as part of the JDK, such concepts would be more generally used in a wider variety of libraries and frameworks than a couple of pure GUI frameworks.
Advice
I suggest considering the MVVM model and other GUI architectures.
If you want a dead-easy framework which follows a model, view, presenter style, definitely give afterburner.fx a spin.
I think the correct choice of architecture depends on your application, your experience and the size and complexity of the problems you are trying to solve. For instance, if you have a distributed system, then you could follow REST principles rather than (or in addition to) MVC. Whichever you choose, the architecture should aid you in solving the problem at hand (and possibly future problems) and not the converse. Over-architecting a solution is a common trap and is very easy to do, so try to avoid it.
Caveat
One caveat to consider is that observables necessarily work via side-effects which can be difficult to reason about and can be antithetical to the concept of isolation. JavaFX features some good tools, such as ReadOnlyObjectWrapper and ReadOnlyListWrapper, to help limit the impact (damage control if you like) on observables so they don't run amok in your system. Use such tools (and immutable objects) with reckless abandon.
Learn from Examples
For a simple JavaFX application which is built using observables, refer to tic-tac-toe.
For a good way to structure a large and complex JavaFX application with FXML based components, refer to the source code for SceneBuilder and SceneBuilderKit. The source code is available in the JavaFX mercurial source tree, just check it out and start learning.
Read up on the JavaFX UI controls architecture. Examine the JavaFX controls source code (e.g. Button and ButtonSkin or ListView and ListViewSkin) to see how concepts such as MVC can be applied using JavaFX structures. Based on that learning, try creating some of your own custom controls using the architecture that the JavaFX controls framework provides. Often, when you are building your own application you don't need to create your own controls (at least ones which derive form JavaFX Control). The JavaFX Controls architecture is specially crafted to support building libraries of reusable controls, so it is not necessarily generally suitable for all purposes; instead it provides a concrete demonstration of one proven way to get certain things done. Adopting and adapting proven solutions goes a long way to ensuring you don't reinvent stuff needlessly and allows you to build on a solid base and learn from the trials of others.
Regarding your Concrete Example
I advise you to go with:
The easiest way to link the "Model" and "View" of my program would simply be to change the "Model" class to have an ObservableList and not an ArrayList
Maybe use a ReadOnlyListWrapper to expose the ObservableList from the MachineMonitor to the outside world, so that nothing can modify it unduly.
Setup some other structure which encapsulates the view (for example a ControlPanel and ControlPanelSkin) and provide it a reference to the read only observable list of MachineMonitors. The ControlPanelSkin can encapsulate a TableView, a graph or whatever visual knobs and widgets you want to use for the user to monitor the machines.
Using such a structure effectively isolates your view from the model. The model really doesn't know anything about the UI at all and ControlPanelSkin implementation could be changed out to a completely different visual representation or technology without changing the core MachineMonitor system at all.
The above just outlines a general approach, you'll need to tweak it for your specific example.
I disagree that using an ObservableList in your "model" class violates MVC separation. An ObservableList is purely data representation; it is part of the model and not part of the view. I (and others) use JavaFX properties and collections in model representations in all tiers of my applications. Among other things in there, I point out how I use JavaFX properties that are (or can be, at least) bound to JSF. (I should mention that not everyone agrees with the approach of using FX properties on the server side; however I don't really see any way to make the argument that they are somehow part of the view.)
Also, if you do
List<MachineMonitor> myNonObservableList = ... ;
ObservableList<MachineMonitor> myObservableList = FXCollections.observableList(myNonObservableList);
myObservableList.add(new MachineMonitor());
the observable list is backed by the non-observable list, so the change occurs in myNonObservableList too. So you can use this approach if you prefer.
Hey guys I'm new to programing and I'm just gettin into UI design.
There are some things I've gotten so far, like I should only use a JFrame per application and other guidelines like that. What I don't understand is... what is the proper way to join your business logic with the GUI?
What I mean is, let's pretend I've just created an application that runs on console (or whatever), and I want to create a GUI for it, so, I've seen on the net that people create a JForm-derived class as a main class and that's it. But is this the proper way? I would like to keep my original "Main class" (the class that uses every other class I've created for my project) and define the form as a field of it, something like that.
Is it possible? If so, how can I achieve this? I have all my logic on that main class I just talked you about, so when I instantiate the form inside of it, I don't know how to make the form use and alter the fields and use the methods I defined in the main class (Sorry if I'm not making myself clear).
How you do, experienced people, do it? What is the "good practice" way? Thanks for taking your time and sorry if it's a noob question.
I'm no professional but I can't stand working with JFrames and Graphics objects.
Most of the time I use the lwjgl library. I know this library is for games but It is
great for UI's as well. The reason it is so easy is because you simply give buttons their
X and Y coordinates without having to worry about layouts. You can make your own images and
import them easily, so if you want your button to look like an image you created no problem.
Because it is made for games it is also very fast and fluid.
This may not be the best way but it works for me so I thought I would share anyway.
Hope it helps.
Here is the lwjgl website: http://www.lwjgl.org/
Here is a video series that helped get me started: http://www.youtube.com/watch?v=0v56I5UWrYY&feature=c4-overview-vl&list=PL19F2453814E0E315
Paranaix already mentioned in his comment about the model - view - controller architecture.
I mostly construct Java Swing GUI applications.
I build the model first. This could be considered a "first cut", since I update the model as I construct the view.
Next I build the view. I construct all of my Swing components by hand. I find that GUI builders harm more than they help. Building the view usually causes me to modify the model.
Finally I construct the controller.
Here's a more detailed description of how I put together a dice game from my blog.
I am just about done with our exam project, and when looking back at what I coded, I feel I did quite alright. Though, stuff could obviously always be alot better. But maybe that's just me.
I was in charge of coding the GUI, and coupling it with the application logic. When making the GUI I made the decision that I would make a class file for every window (e.g. LoginWnd.java), and actually build the GUI in the constructor. I would initalize everything and set all data inside this constructor.
Then in order to navigate through the application, I would set actionlisteners on the jbutton. For example, in SearchWnd, hitting the "Search" jbutton would create a new object of ResultWnd with some specified parameters.
Now i'm kinda wondering: Was this design decision bad in any way? Are there any design paradigms that I should've been aware of?
Thanks.
Your approach sounds fine overall - as long as it works you've achieved the main goal! So my comments here are more about fine-tuning / broader design aspects.
There's nothing fundamentally wrong with doing GUI construction in the constructor providing that the GUI doesn't subsequently change during program execution. The rationale here is that constructors should be reserved for "one-off" construction activities. So it's probably fine for dialog boxes and suchlike that have a pre-determined layout.
If you have a more dynamic GUI where components are frequently being added and removed throughout program execution, then I'd strongly suggest moving this to a set of methods outside the constructor so that they can be called independently of object construction. The constructor itself can still call these methods if needed to do initial setup, but subsequently you have the ability to call these methods later to add new components, refresh the layout etc.
The good news is that this stuff isn't hard to refactor if you get it wrong - it's usually trivial to pull setup code out of a constructor into separate methods later if needed.
Another thing to be aware of is the oft-repeated mantra "prefer composition to inheritance". That is to say, if you can make your GUI work by assembling existing components rather than inheriting and overriding your design will probably be better/more easy to maintain in the long run. For example, I don't think I've ever subclassed JFrame - it's almost always cleaner to just add JPanels within it that contain all the application-specific components.
Finally, be cautious of coupling your GUI components too closely to your application logic. Swing actually does a pretty good job of encoraging you to separate out your data model from the presentation code (e.g. with ListModel and friends). It's worth studying and understanding that approach. The point is that you should usually build GUI components in a way that is fairly application-agnostic, but give them application specific behaviour by connecting them to the right data model and event handlers etc.
I also initialize my GUI in the constructor, so it can't be bad :) But when it gets too long I extract parts of the code into separate GUI components.
I'm putting together a GUI with a couple of panels.
In one panel there are components for the user to input various parameters.
In another panel, there are buttons and a place to output a plot based on data
generated using the user inputs.
I have all of the various pieces working independently now I'd just like them to
talk to each other!!
When i hit one button, I would like to take all of user inputs and combine them to
generate a data set and plot it.
Another button then to write this same data to a file.
I have code to implement all the components individually, code to write data to
a file and code to generate a plot from data. All of which works fine.
I thought that I could use the Action/ChangeEvents to take the parameters and
assign them to an ArrayList. Then use this arraylist to generate the data.
I'm finding it difficult to plan an approach to tackling this.
Currently I'm using get set methods in the event handlers to set parameter levels for
a particular instance of the array list, I would like to pass this instance into another class to generate the data but don't know how to make it accessible.
I hope I have provided enought information here. If anyone has any
thoughts on this they would be much appreciated.
I think a structured way to tackle your issue is to apply the MVC pattern. Here is what I think a seminal article about Model-View-Controller (MVC) using Java.
Java SE Application Design With MVC by Robert Eckstein,
and here is another sample code.
As for taking the parameters from one panel and pass them on to the other panel, you can use the Command Pattern. What the pattern does is basically encapsulate all the information needed for a method to perform (an instance of a class, parameters, etc.) into one Command. This Command then can be passed around in the application, simplifying the way you execute the method.
A good book about Design Patterns, by the way, that I really love is Head First Design Pattern.
EDIT:
I'd just like to add some links discussing about MVC and some other GUI architectures that I find useful:
GUI Architectures by Martin Fowler
Build your own Composite Application Block series: UI Architechtures, Patterns and WinForm Examples
MVVM vs MVP vs MVC: The differences
This seems like a good case of application of MVC pattern:
http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
Another good resource would be this book's second chapter:
http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612/ref=sr_1_1?ie=UTF8&qid=1334437965&sr=8-1
What are some good design patterns for creating a form in java?
I have an app that has 6 tabs with a different form in each. How does the typical java programmer go about making these items accessible?
For example as a wpf programmer I might databind all these controls to underlying objects.
What do java programmers like to do?
I don't know what programmers like to do, but you should listen to what MVC patterns tells.
And it tells you that each view should have its controller. Your view has obviously subviews. So the design in this case would obviously be following:
MainView
Label1
Text1
Tab1Subview
Label1
Text1
Tab2Subview
Label1
Text1
MainViewController
Tab1SubviewController
Tab2SubviewController
And controllers will define the binding for each particular view. You can also use one single controller for all subviews and bind it inside. Your main controller could have a link to main root model object e.g. Forms. And particular controller could bind subobjects. As I already said again - you can go with one big controller and bind it all in one place.
This is for what MVC was created.
Tools
If you are looking for SWT graphical designer, then the Window Builder Pro (Eclipse Plugin) - is definitely is the choice (not perfect although, but the better of all available).
Things like EMF is quite complicated. You can start with a mix of Window Builder Pro and coding and as mentioned above JFace Binding API will be an option - but it's not necessary - depend on model you can use either JFace Binding or do it yourself in the code.
For saving simple form all you have to do is write something like save method, e.g.:
person.setName(view.getFullNameTextField().getText());
this is not much worse than using advanced binding features, especially if you don't won't dependance on extra libraries like JFace.
If you are using Eclipse, you can try EMF, an amazing framework helps you to design your model, generate Java code, and provides a pretty cool model editor in minutes.
EMF provides data binding between the UI widget and the model, you can read the generated code to see how it works.