JavaFX getText not working [duplicate] - javafx

Maybe a really newbie's question....
I'm starting learning JavaFX in a FMXL Application using the Scene Builder, by reading this tutorials:
http://docs.oracle.com/javase/8/javafx/get-started-tutorial/fxml_tutorial.htm
So once i applied some changes, an issue with this 2 IDs came up... I might have missed or confused something about them...
Can anyone tell me in which cases they are used one or another?

id you use to set a CSS ID to your Component, for example <Text id="welcome-text" .../> and in your stylesheet you have something like #welcome-text { font-size: 16pt; } so this will be applied to your Text.
fx:id you use if you want to work with your Components in your Controller class, where you annotate them with #FXML Text myWelcomeText.

The fx:id is the identity associated to component in fxml to build a controller, and the id is used for css.

I took a look at an FXML document generated using the JavaFX Scene Builder. You access controls from Java Controller with the fx:id. (edit) I stand corrected, the id does matter.
You can apply css from the FXML document like this:
<Slider id="css_id" fx:id="myslider" styleClass="style_name" .../>
(Replace slider with any control)
And Java controller interaction:
#FXML
Slider myslider;

In JavaFX id is used to set a CSS ID to a component. And fx:id is used for accessing that component in code (i.e. in a controller class). fx:id works like a components name.

Related

Change colour of Shape in JavaFX controller [duplicate]

Maybe a really newbie's question....
I'm starting learning JavaFX in a FMXL Application using the Scene Builder, by reading this tutorials:
http://docs.oracle.com/javase/8/javafx/get-started-tutorial/fxml_tutorial.htm
So once i applied some changes, an issue with this 2 IDs came up... I might have missed or confused something about them...
Can anyone tell me in which cases they are used one or another?
id you use to set a CSS ID to your Component, for example <Text id="welcome-text" .../> and in your stylesheet you have something like #welcome-text { font-size: 16pt; } so this will be applied to your Text.
fx:id you use if you want to work with your Components in your Controller class, where you annotate them with #FXML Text myWelcomeText.
The fx:id is the identity associated to component in fxml to build a controller, and the id is used for css.
I took a look at an FXML document generated using the JavaFX Scene Builder. You access controls from Java Controller with the fx:id. (edit) I stand corrected, the id does matter.
You can apply css from the FXML document like this:
<Slider id="css_id" fx:id="myslider" styleClass="style_name" .../>
(Replace slider with any control)
And Java controller interaction:
#FXML
Slider myslider;
In JavaFX id is used to set a CSS ID to a component. And fx:id is used for accessing that component in code (i.e. in a controller class). fx:id works like a components name.

Can I automatically generate controller classes from FXML?

As I understand it, when using FXML to describe a Java FX scene, the controller class is written manually and it's member variables and methods can then be referenced from the .fxml file. When loading the scene using the FXMLLoader, member variables are set to the corresponding scene elements and methods are wired up to the corresponding events automatically. This works but is very cumbersome as changes need to be done in two places and any mistakes will only show up at runtime.
I've seen other GUI frameworks that allow you to instead generate the controller from a scene description as an abstract class which needs to be implemented to access the scene elements and handle the events. An example of what I mean:
I would create the following .fxml file (e.g. using the JavaFX Scene Builder):
<AnchorPane ... >
<children>
<Button fx:id="button" ... text="Button" onAction="#buttonPressed" />
</children>
</AnchorPane>
Somewhere in my build process, the following .java file would be created (e.g. using a Maven plugin):
abstract class TestController {
protected final Parent root;
protected final Button button;
{
// Load test.fxml file
// Assign scene elements to root and button
// Attach event handler to the button that calls buttonClicked()
}
protected abstract void buttonClicked(ActionEvent event);
}
I could then, possibly multiple times, create a concrete implementation of that controller:
final class TestControllerImpl extends TestController {
TestControllerImpl(String buttonLabel) {
button.setText(buttonLabel);
}
#Override
protected void buttonClicked(ActionEvent event) {
button.setText("I've been clicked! What a great day!");
}
}
Is there a project with the goal to do this? Or is there a problem with this approach applied to FXML?
I see the following benefits from this approach:
Declarations for member variables and methods for the controller are automatically generated.
All member variables are final and protected instead of non-final and either public or annotated.
The same for methods, they are protected instead of either public or annotated.
Not implementing a method or misspelling it's name will lead to a compiler error.
Programmatic setup of the scene can be done in the constructor instead of an initialize() method because the constructor will run after the scene has been loaded and its elements assigned to the member variables.
This is now supported in SceneBuilder, NetBeans and in Eclipse. Note this works out of the box in NetBeans and SceneBuilder, but in Eclipse you first need the e(fx)clipse plugin.
SceneBuilder:
With an FXML file open in the editor, enter the menu to select "View" and "Show Sample Controller Skeleton".
Eclipse:
Open the fxml file so the contents are displayed in the code editing pane (you should see the fxml as plaintext xml with syntax highlighting inside Eclipse, not rendered visually in SceneBuilder). Right-click on the code in Eclipse and select "Code" and then "Generate Controller".
NetBeans:
In NetBeans it is even easier, right-click the fxml file in the project explorer and select "Make Controller".
Update Nov 2020
This answer is now outdated.
As various more recent answers have pointed out, there are now a variety of additional different tools available for automatically generating FXML controller classes from FXML documents. Many of these are targeted as extensions, features or plugins to existing development tools, such as SceneBuilder, Idea, Eclipse or NetBeans.
I suggest that interested readers review both this answer and other answers to this question, then look at their individual use-case and toolset chain and choose the solution which is most appropriate for them from the available choices.
There is nothing I know that does exactly what you propose in your question.
Likely this answer will probably end up pretty outdated over time.
Alternate Technologies
JRuby achieves most of your outlined benefits using a slightly different approach - it uses jRuby's dynamic programming magic to automatically create Ruby class members from the FXML dynamically a runtime.
Tom Schindl wrote a tool which generates Java code from FXML. Of the approaches listed in this answer, Tom's tool seems closest to your question.
SceneBuilder Skeletons
A similar Java code generator from FXML is available in SceneBuilder View | Show Sample Controller Skeleton feature, which is described in this blog post. When I use SceneBuilder, I use this feature all the time and try to keep my controllers really light so they are almost all auto generated code from the SceneBuilder skeleton feature.
It is slightly annoying though because it doesn't achieve a clean separation of generated code from hand written code, so you need to be careful when you do updates to the FXML and want to generate a new skeleton and copy and paste it over parts of your existing Controller (plus that is a slightly error prone manual operation that takes a little bit of developer time).
Source code for SceneBuilder is available if you want to see how it works.
Potential Build Tool Plugins
Such a code generation feature might make a worthwhile addition to some of the existing build tools in the JavaFX ecosystem, such as the JavaFX Maven plugin or JavaFX Gradle plugin (or a separate plugin in it's own right).
Future Development
I believe that Oracle are also working on a feature extension for FXML for a future JavaFX release (post Java 8) which compiles FXML directly to Java byte code (class files), bypassing the Java source code step. This kind of feature would probably achieve most of your outlined benefits.
It is possible with NetBeans version 8.
Open FXML , go to Source and click generate controller.
Edit: Now can be done in any IDE , Eclipse needs a plugin thought.
For Intellij Idea IDE users, FXMLManager to the rescue. See the plugin homepage
"When clicking right mouse button on .fxml file, there is new menu item "Update Controller from FXML".
Clicking this item will modify FXML Java Controller:
Remove all #FXML fields that are missing in FXML and their getters/setters
Add all #FXML fields that are missing in Controller
#Deprecate all ActionEvent methods that are missing in FXML
Create all ActionEvent methods that are missing from Controller"
As I know, there are two kind of solutions exist in netbeans.
First, netbeans's internal feature "Make Controller", which you can see with right mouse click on the fxml document. it will generate controller class which will work with FXMLLoader. The controller's java file name should be indicated in the fxml document. (left panel -> Controller -> Controller class)
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Second, netbeans's plugin "FXML 2 JAVA Converter", which you can install from menu (Tool -> Plugin -> Available Plugin -> FXML 2 JAVA Converter). and you can see "Generate Abstract Class" menu item with right mouse click on the fxml document. It will generate source code from fxml document and you can use it as an abstract class without using FXMLLoader like normal JavaFX project not JavaFXML project.
Now you can easily do it with eclipse Just do these simple steps :
Go to your fxml file that you want to create Controller for
Right Click and Click source
Click Generate Controller
Click here to see the Picture of How to do it.
If you're using IntelliJ ide, you may have to try FXML Helper plugin.
First, install the plugin from the File | Settings... | Plugins. After the installation restart the ide, Now right click on the .fxml document and select the FXML Helper menu. That`s all.
#Feuermurmel
no there is not any ways to generate automatically controller class for particula .fxml file.
you should define dynamically declare variable and method with anotation #fxml and set(bind) in scence builder.

How would I include an MXML file inline another MXML file?

I would like to include an MXML file in my MXML file in the same way you can include an external file in AS3 using the include directive. Using the include directive brings the code from the external file into the original file at compile time placing it in the same scope.
For example,
Application.mxml:
<Application>
<source="external.mxml"/>
</Application>
External.mxml:
<Styles/>
<Declarations>
<Object id="test"/>
</Declarations>
I need to keep this code/mxml/xml in the external file in scope with the original. Do not ask me why I want to do this.
Another example. Here is my current code (simplified) all in 1 mxml file:
...
File1.mxml
<Button click="clickHandler()"/>
<Script>
public function clickHandler():void {
}
</Script>
...
Here is what I want:
...
File1.mxml
<Group>
<source="File2.mxml"/>
<Button click="clickHandler()"/>
<Group>
File2.mxml
<Script>
public function clickHandler():void {
trace(this); // File1.mxml
}
</Script>
...
I want to split my code out into a separate file...
~~ Update ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Though NOT what I was asking for using a "code behind" scheme achieves partial credit to breaking the code out of the view. So I create a MXML file, MyGroup.mxml or MyGroup.as and that extends Group that contains the clickHandler code.
The problem with this method is that I am then locked to the class type I'm extending, hardcoding the view. So for example I would have to extend Group if the MXML class I want to split into separate files is a Group.
I've worked on projects where this was done and it is not good. People start setting styles and visual aspects or group / view specific properties in the code behind class and later if or when we need to change it or the layout it we have end up with all these dependencies to the container. It becomes a mess. Plus, using Code Behind you can't reuse it (reuse in the way include styles.as is reused). So this is not a solution but thought I'd mention it.
Here is a code behind example,
MyGroupBehind.mxml:
<Group>
<Script>
public function clickHandler():void {
trace(this); // File1.mxml
}
</Script>
</Group>
MyGroupAhead.mxml:
<MyGroupBehind>
<Button click="clickHandler()"/>
</MyGroupBehind>
MXML is converted into a class by the compiler, so there is no way to do what you are asking.
Personally, I think that is a good thing. Breaking things up into separate files does not equal "more organized". In fact I would say it achieves the exact opposite effect. You would do better to focus on a proper component structure, IMHO.
Just start typing the name of your custom component, then press Ctrl+Space. Code completion will populate a list of possible things you might want to add, including the name of your component. Use the down arrow to select your component's name, then press enter. Code completion will set up the namespace and start the tag for your component. If you go to the end of the line and type "/>" (no quotes), voila! you will have an inline tag that represents your custom MXML component.
First of all, any external mxml should be a valid XML. Now, as long as you have a valid MXML file, you simply add it by its name like below:
<Application>
<external:External/>
</Application>
Where 'external' is the namespace for your External.mxml file.
Say my MXML file is called Example in the views folder. Simply call it within the parent MXML file you want this to be in
e.g.
<views:Example/>

How to bind property of View to property of class using Flex MATE

Lately i discovered MATE (for Flex development) and was wondering: how do i bind a property in a view (actually a navigatorcontent component) to another property in a class so that they stay in synchronization (meaning that whenever the property in the class changes the property in the view also changes).
So if we have a view called Target.mxml and a property targertProp how do we bind it to the class called SourceClass with property SourceProp?
Thanks in advance
For future use:
fiction has answered the question correctly.
Actually it should have been formulated this way!
<Injectors target="{Target}">
<PropertyInjector targetKey="targertProp"
source="{SourceClass}"
sourceKey="SourceProp"/>
</Injectors>
Of course SourceProp must be [Bindable]
Read my article below
http://vinothbabu.com/2010/03/21/introduction-to-mate-framework/
on how you use the Injectors Tag to play with. Its a very simple example. Let me if you were looking for something else.

address a Flex checkbox in a component

I have a checkbox in a component:
<s:CheckBox id="myCB_1" />
In my main.mxml I need to test for the state of the checkbox. I originally had all my code in main.mxml, but it was getting really long, and I thought that it was better practice to break my code into components. Also, I have other projects where the same concept will apply, so I really want to figure this out.
I have the following function :
private function checkAlarms(currentTime:Date):void
{
if (!breakfastAlarmSounded)
{
if ((currentTime.hours > breakfastTime.hours) || ((currentTime.hours == breakfastTime.hours) && (currentTime.minutes >= breakfastTime.minutes)))
{
if (myCB_1.selected)
{
playBreakfastAudioAlarm();
}
if (myCB_2.selected)
{
playBreakfastVisualAlarm();
}
breakfastAlarmSounded = true;
}
}
...
simply addressing the component, as in:
myComponent.myCB_1.selected
doesn't work. Someone mentioned that I need to create a variable in my component that refers to the id (myCB_1) of checkbox, but I don't really understand or know how to do that, and they didn't elaborate.
How do I test for the status of the CheckBox "myCB_1" in the component from within my main.mxml?
many thanks,
Mark
(newbie)
With very little information, I'm going to suspect you originally had the CheckBox included in main.mxml and moved it to a custom component. If so, you need to address the CheckBox's ID via the custom component's ID. Something like this (from main.mxml):
if(yourComponentsID.myCB_1.selected)
{
...
}
If this isn't the case, please edit your post and give us more detail.
EDIT
You said you created a new custom component and moved the CheckBox into it. Great, that's a helpful start :) When you included your new component in your main.mxml file, it should look something like this:
<component:YourNewComponent />
Of course, however you named it (and whichever namespace is used to reference it) will be different from my example, but the principle should still apply. In main.mxml, you need to give your custom component a unique ID string so you can reference it within main:
<component:YourNewComponent id="myComponent" />
From here on, you should be able to reference the component, and any public elements within it: myComponent.myCB_1.
It would be useful to provide more details about the context in which you're using this script. Nonetheless I'm going to throw out some information that may help.
In order for the script to access the component, it has to be within the scope of the component. Usually that means one of the following:
You have a <script> tag in the MXML, with code in it that references components within the same MXML file.
You have a <script source='external.as'/> tag in the MXML, where external.as is referencing components in the MXML file.
You are creating the component in your script and you have a definition for the component within ActionScript (ex. var myCB_1:CheckBox; is within the class definition).
If the script and the component aren't within the same scope then they can't see one another.
You need to refer to the checkbox through the component. Lets say that you use your component in your main like this:
<local:MyComponent id="myComponent" />
In your script, you want to refer to it:
if(myComponent.myCB_1.selected) { // do something }
Strangely enough, it works. I was getting a getting an 1119 error (Description 1119: Access of possibly undefined property myCB_1 through a reference with static type Class.) when I refer to the component with dot notation (myComponent.myCB_1.selected) and an 1120 error (Description 1120: Access of undefined property myCB_1) when not addressing it via myComponent.
With these errors I never thought to try running the thing. Long story short - it runs with or without addressing the component (???) go figure!
thanks for all the input and would love to hear any other comments.
MCE

Resources