Hello guys, I’m back after my lots of works and stuffs that’s why this post got delayed. Anyway now I’m going to demonstrate today about how to communicate between FXML using FXController classes. Some of my commentator also asked me to share this communication of FXML so I’m blogging for the same. Today I’m going to just continue the blog post of previous post I’ve blogged about FXML Stuffs (include and define) . So If you have not started reading those previous blog then please have a look because the things I’m going to tell is related to them.
Anyway Let’s summarize the previous blog.
Main.fxml (The main container of all fxml)
Home.fxml (the tab content of Home Tab)
About.fxml (the tab content of About Tab)
FXMLTest.java (this is just the executor class)
Now In today’s post we are having one more extras class which is listed below.
DockletListener.java (The java interface)
Before going to start this communication between fxml . Let’s have a look at how the flow gets working.
DockletListener.java
1 2 3 4 5 6 7 |
public interface DockletListener { //Dock item being added void added(Node n); //Dock item being removed void removed(String id); } |
What we see in above flow is that there is always an Interface DocketListener.java
which have functions like added()
, removed()
. This helps the Main.java(Main.fxml) to know what’s being added/removed. The approach I’m using is like a Swing Listeners style. This interface works by living in the middle of FXController
classes. Ok Let’s move to the Main.fxml
which helps to listen the event of this interface.
Main.fxml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
<?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <?import javafx.scene.shape.*?> <?import javafx.scene.effect.*?> <?import fxmlstuff.Main?> <?import javafx.geometry.Insets?> <Main xmlns:fx="http://javafx.com/fxml" fx:controller="fxmlstuff.Main"> <padding> <Insets right="10"/> </padding> <fx:define> <fx:include source="Home.fxml" fx:id="homeContent" /> <fx:include source="About.fxml" fx:id="aboutContent" /> </fx:define> <center> <TabPane fx:id="tabpane" translateY="5" translateX="5" > <tabs> <Tab text="HOME" fx:id="homeTab" content="$homeContent" closable="false" /> <Tab text="ABOUT" fx:id="aboutTab" content="$aboutContent" closable="false"/> </tabs> </TabPane> </center> <!-- This is the bottom part containing Dock Panel --> <bottom> <StackPane translateY="-30" visible="true"> <effect> <Reflection topOpacity="0.7" fraction="0.8" topOffset="-30"/> </effect> <children> <!-- Dock Panel as Shape --> <Polygon fx:id="dock_bottom" /> <!-- Dock Items Panel --> <FlowPane hgap="20" translateY="-25" fx:id="dockPanel" alignment="TOP_CENTER" /> </children> </StackPane> </bottom> </Main> |
Main.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
" ]public class Main extends BorderPane implements Initializable, DockletListener{ //FXML ATTRIBUTES @FXML private Home homeContent; @FXML private About aboutContent; @FXML private Polygon dock_bottom; @FXML private FlowPane dockPanel; @Override public void initialize(URL url, ResourceBundle rb) { // Adding Swing style of custom Listener aboutContent.addListener(this); homeContent.addListener(this); //This is for Dock bottom part which is a polygon double slide=50; double height =15; double width= 700; double offset = 20; dock_bottom.getPoints().addAll( slide, 0.0, 0.0, height, width,height , width-slide, 0.0 ); //Default Dock Item added added(ButtonBuilder.create() .text("Dock") .id("default") .build() ); } /** * This is the implemented method of Node being added to docklet * @param n Node */ @Override public void added(Node n) { if(dockPanel.getChildren().size()<5){ //Let's assume currently we make dock item of only Button final Button b = (Button) n; b.setPrefHeight(50); b.setPrefWidth(60); b.getStyleClass().add("dock-item"); dockPanel.getChildren().add(b); } } /** * This is the implemented method of Node being removed from docklet * @param n String */ @Override public void removed(String id) { Node rm = null; //Checking for dock item according to it's ID for(Node n:dockPanel.getChildren()){ if(n.getId().equals(id)){ rm = n; break; } } if(rm!=null){ final Button b = (Button)rm; dockPanel.getChildren().remove(b); } } } |
Now What we see in Main.java
it implements the DockletListener
interface and has overridden the methods added(Node n)
and removed(String id)
. Now this class can easily listen which node to be added in docklet and which is to be removed. Currently We are adding only Button Node
as an item in Docklet. These added,removed will be invoked by Home
and About
fxml. As you can see in highlighted lines above; I’ve added the addListener(this)
to help the Home/About class to invoke via this a.k.a. Main.java
object which is instance of DockletListener
.
We have two tabs “Home” and “About” . I’ll only describe “Home” tab because both fxml and classes have almost identical codes. Here we have distinguish our dock item by the help of id
. We can remove the items by the help of “id”. Whenever the id==home then the item will be deleted from the docket. In the Home.fxml
I’ve added one button of ‘remove’ and some layout too.
Home.fxml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <?import fxmlstuff.Home?> <Home id="homeContent" xmlns:fx="http://javafx.com/fxml" spacing="10" translateY="40" translateX="20" fx:controller="fxmlstuff.Home" > <children> <Label text="Add New Dock of Home" /> <HBox spacing="10"> <children> <Button text="Add !" onAction="#handleAction" /> <Button text="Remove !" onAction="#handleRemoveAction" /> </children> </HBox> </children> </Home> |
Here the “Add” button trigger the function to invoke the add item in docklet. And the “Remove” button to delete the item from docklet.
Home.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
" ]public class Home extends VBox implements Initializable{ //Static listener instance of DockletListener private static DockletListener listener; @FXML private void handleRemoveAction(ActionEvent event) { if(listener != null){ listener.removed("home"); } } @FXML private void handleAction(ActionEvent event) { if(listener != null){ listener.added(ButtonBuilder.create() .text("Home") .id("home") .build()); } } @Override public void initialize(URL url, ResourceBundle rb) { } public void addListener(DockletListener listener){ Home.listener = listener; } } |
The highlighted lines in above code tell the Home.java to addListener
of the DockletListener
instance. And now when the “Add” button trigger then the handleAction()
takes the job to add item to the docklet by the same instance which was added as Listener.
Now if you run your program with the same FXTest executor then it will now easily take the event of Home.fxml and the effect goes on Main.fxml.
I’ve modified even more in this app and I’m going to give you the screenshot of that app.
To view demo of this app : DockletDemo
That’s all for today. Also you can share your views and ideas about FXML Communicate just below at the comment.
Have a good 🙂 day.
Thanks
My short bio
The code labeled “Main.fxml” is actually Home.fxml, and you forgot to show us the actual Main.fxml, without which we can’t build this example.
Hi Bill,
Thanks for figuring out my error. Actually I had kept xml codes but this wordpress automatically cut those xml due to HTML format. Ok I’ve updated it.
Thanks
Thank you very much Narayan. This is a wonderful tutorial.
Okay, now it runs. But it illustrates the same controller confusion I mentioned about your previous post. Your example only works because you declared the “listener” field static in Home and About. That’s not good programming practice, and it’s not a sustainable design pattern for using FXML. In this toy case, where you only ever have one instance of Home or About, you can get away with it. But in real-world examples, an application often uses a control more than once — e.g., a custom control used to display each item in a list view, or the layout for a property window that you might have multiples on the screen at once.
It doesn’t seem like the FXML designers really thought this one through. They don’t make it easy for a controller and the code that created the control to communicate. I may have to write a blog post on this myself.
By the way, you don’t need @FXML on the listener field — it’s not referenced in your FXML file.
Hi Bill,
Yes I do prefer your points for ‘static’ concept. Currently in FXML I’ve not found any good control for talking between FXML. I’ve read the documentation and somehow I found that the FXML can handle the ‘static’ property. So by using this static concept I’ve presented this post.One more thing; I’ve made the static variable ‘listener’ but I’ve made them private so it doesn’t violate the Java good programming. As I’m a GUI Developer I also felt awkward for this methodology.
I’ll be waiting for your new post.
Thanks for your comment. I really appreciate with your views.
In lieu of a blog post, I summarized my current views on the Java FX forum — https://forums.oracle.com/forums/thread.jspa?threadID=2345375, which I see you have already found.
Greetings from Philippines!
Hello Sir,
I hope you can do a tutorial on mac os style dock menu. I have seen one written in JavaFX Script but not as good as the mac os. One that come close is from ZK web framework. http://www.zkoss.org/zkdemo/menu/fisheye_menu
Thanks
@Rey
For doing on mac style is just same..!! Use some effects and gradient . If possibly you can use SVG path for making exact dock of MAC 🙂 I’ve tried once exactly same when I was playing with some effects and CSS. I used photoshop to firstly copy cat the design.
Thanks
Narayan
Hiii Dear
This is farhan from mangium infotech i want to ask one thing that i have to take image dynamically by using filechooser then i have to set border on the image view but it is not comming and how i can set the zooming and drag the image view when i have taken image dynamically please send me the code on my mail if possible .
Hi farhan,
Please use the FileChooser and preview the instance of image in the Scene then for zooming and drag use some concept of scaleX,scaley,LAYOUTX,LAYOUTY property of ImaveView Class.
Thanks
i want know how to add a checkbox to a column of tableview in javafx scene builder.
Hi @ananth
Use the cellFactory implementation. You can see somekind of work around of the tablecell in here : https://blog.ngopal.com.np/2011/10/01/tableview-cell-modifiy-in-javafx/
Thanks
Thank u.
I want to know how to access one fxml file elements into another fxml file?
Hi, till now I have developed javafx app such that when ever we run the application the window(o/p) is showing. But here I need an app which should not show the window immediately. It should show the stage only when some event occurs. For instance,
I have created one java which can detect any file/folder manipulations under one folder. Here when ever I create any folder, one method will execute then only Javafx app should call stage.show(). This is some thing like Integrating javafx with general Java code. Please let me know how to achieve this.. It will be helpful to so many.. [I am using Javafx with fxml]..
You can create the multi-threaded javafx which helps you to make the thread alive even without the Javafx stage close event.
Some procedures
1. Create New Async Java Thread like a daemon thread
2. Create JavaFX Thread only when any event is occured other wise just close that thread using Task . In this thread you will instantiate new Stage object and run.
3. Finally close the daemon thread when all your job is completed.
Thanks
Narayan
HI, I want to know how to implement mdi(multiple document interface) in javafx..
hi,
please reply for #17 query.If javafx does not support MDI approach then please try to send me the implementation details of integrating swing in javafx.
Hi @ananth,
Sorry for the late response due to busy days. Anyway if you want to make use of MDI approach in your javafx application then you probably need to use some pre-built library of some javafx geeks. Like VFXWindows which helps to make multi window inside your javafx scene. Currently the JFXTras project does contains VFXWindows library as well. Refrence: http://mihosoft.eu/?p=392
Thanks
Narayan
Thank u very much..
Hi,
I need one more help from you..
when i deploy javafx aplication in web browser it will not fit to screen.
so how to achieve it.
hi,
How can i execute javaFX application in web browser that should fit to the screen?
@ananth,
Use the width = 100% and height=100% without any html text content in your javascript launcher arguments of your javafx.
Thanks
Narayan
Thank you.
Hi,
How can achieve multi scene interface under single stage with common menu bar in javafx ?
I am using javafx scene builder to build Gui’s.
Please reply to #25 query.
Thanks
Ananth
@ananth,
you mean to add multiple scene in a single stage? If so then it is not possible to add more than more scene in a stage but you can however make use of replacing the multiple scene in stage one at a time. To share your node between scene you must remove from the scene1 container and then add them in scene2 container .
Thanks
Narayan.
ok thank you..please can you provide any reference to this.
@ananth,
well for that you must do some coding manually 😉 HEHE
hi,
As you have specified i have used width=100% and height =100% in javascript function but it is applied only for the first scene but the second scene will not fit to the screen.
hi,
i am swaping scene’s in single stage. i want to run this app in browser i have used height and width as 100% in html page but it is applied only for the first
scene the second scene will not fit to screen the second scene is taking the size give in scene builder..i need your to sort out this problem.
Type your comment here
Hi ananth,
Bind your scene height and width with your stage height and width this will work .
THANKS
HI,
As you have suggested to bind scene height and width with the stage..
but i am not getting it.. i have hard codded height and width value of the parent node in the scene builder and in html file i have used width and height =100% ..but i want the app to fit in every screen so please help me in implementing this.
HI @ananth,
As you have suggested to bind scene height and width with the stage..
but i am not getting it.. i have hard codded height and width value of the parent node in the scene builder and in html file i have used width and height =100% ..but i want the app to fit in every screen so please help me in implementing this. Use something likethis
In JNLP Script
width:100%
height:100%
In JavaFX
Use some tricks to make use of
scene.widthProperty()
scene.heightProperty()
thank u very much.
hi
I have a problem in implementing popupwindow in javafx.
I don’t know how are you doing for displaying popup but it’s just easier like displaying stage.
when I am displaying through stage the maximize and minimize appears but I need to get the popup window without the maximize and minimize button like confirmmessage in the swings.
Hi
I am facing problem when trying to open the javafx application(webstart and browser embeded) in some systems through server after deploying it into tomcat server
@Vijay,
Plese refer to https://blog.ngopal.com.np/tiny-forum/?mingleforumaction=viewtopic&t=5.0#postid-9
Thank u for the first query
Can u help out in the second query I have deployed javafx application by copying the files in the server it is working good in some systems but in some systems the FXML file not rendring in the browser and in webstart application i am getting runtime error
HI
I came to know that javafx 2.0 does not contain Datepicker api then how can
i implement datepicker in my application. i am using javafx fxml application.
Hi,
I am coding an event for menuitem and i have included the below line
stage.initOwner(((Window)event.getSource()).getScene().getWindow());
When i click on menuitem it is giving an exception
java.lang.ClassCastException: javafx.scene.control.MenuItem cannot be cast to javafx.scene.Node
How to over come it