This question already has an answer here:
javafx 8 compatibility issues - FXML static fields
(1 answer)
Closed 8 years ago.
I'm introducing in javafx and i found it very interesting. But I have got a problem that i can't solve.
In the simplest case of a Hello World I can't put a #FXML public static var like this:
public class FXMLDocumentController implements Initializable
{
#FXML
public static Label label;
#FXML
private void handleButtonAction(ActionEvent event)
{
System.out.println("You clicked me!");
label.setText("Hello World!");
}
}
If I change it to private it works.
The cause of that I want to made this vars publics is because I'm using diferents controllers for diferents views (in my real app) and i want to communicate between theirs.
PS: Sorry for my bad english
You should not use a static field here. Your controller belongs to one view and every time the view is created by the FXML Loader new instances of all nodes in the view will be created. SO by calling the FXML Loader 2 times you will receive 2 instances of the view. In addition a new instance of your controller class will be created whenever you load the view by using the FXML viewer. By using a static field you will override values of old controller instances and this will end in horrible bugs. Here is a short introduction to the static keyword: What does the 'static' keyword do in a class?
If you just remove "static" it will work.
Instead of using public fields you should add getter and setter methods to your controller class and mark the field as private: Why use getters and setters?
I want to do something similar like this:
I'm working with tabs and i have this two controllers:
FXML_Tab1Controller.java:
public class FXML_Tab1Controller implements Initializable {
FXML_Tab2Controller tab2controller;
#FXML public Label Label1;
#FXML public TextField TextField1;
#FXML public Button Button1;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
#FXML private void actionButton1(ActionEvent event)
{
Label1.setText(tab2controller.TextField2.getText());
}
}
FXML_Tab2Controller.java:
public class FXML_Tab2Controller implements Initializable {
FXML_Tab1Controller tab1controller;
#FXML public Label Label2;
#FXML public TextField TextField2;
#FXML public Button Button2;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
#FXML private void actionButton2(ActionEvent event){
Label2.setText(tab1controller.TextField1.getText());
}
}
something similar like that video:
https://www.youtube.com/watch?v=XLVx46ycxco
Related
I have 3 fxml files:
Main.fxml
Menu.fxml
Manager.fxml
and controller for each.
I need to controll BorderPane center of Main.fxmlfrom both remaining, so I fx:include'd them, gave them fx:id and also set included element Manager.fxml visible = false (only menu button set Manager to center of BorderPane ) but now I'am lost and dont understand how to set included fxml visible when button in Menu.fxmlis pressed. Easy when its about simple element but dont work same with included fxml file.
At the beginning I had only menu inlcuded in Main.fxml and method setCenter in its controller that i used to switch center element using MenuController.java but then i couldn't find way to set main center using manager (so manager could be swithched with other one) becouse FXMLloader only loaded Main and Menu so couldnt set proper MainController instance in ManagerController.
My code before change:
public class MainAdminController {
#FXML
private AdminMenuController adminMenuController;
#FXML
private BorderPane adminBorderPane;
#FXML
public void initialize(){
adminMenuController.setMainController(this);
}
public void setView(String fxmlPatch){
adminBorderPane.setCenter(Fxml.loadFXML(fxmlPatch));
}
}
AdminMenuController
public class AdminMenuController {
public static final String MANAGE_ACCOUNTS = "/fxml/admin/ManageAccounts.fxml";
public static final String MANAGE_ADMINS = "/fxml/admin/ManageAdmins.fxml";
public static final String CHANGE_PASSWORD = "/fxml/ChangePassword.fxml";
#FXML
private MainAdminController mainAdminController;
public void setMainController(MainAdminController mainAdminController) {
this.mainAdminController = mainAdminController;
}
#FXML
private ToggleGroup adminButtons;
#FXML
public void viewManageAccounts() {
mainAdminController.setView(MANAGE_ACCOUNTS);
}
#FXML
public void viewManageAdmins() {
mainAdminController.setView(MANAGE_ADMINS);
}
#FXML
public void viewChangePassword() {
mainAdminController.setView(CHANGE_PASSWORD);
}
}
public class ProjectxController implements Initializable {
#FXML
private AnchorPane LandingPane;
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
#FXML
private void onLoad(ActionEvent event) throws IOException{
pane = FXMLLoader.load(getClass().getResource("connectedPage.fxml"));
LandingPane.getChildren().setAll(pane);
}
Note: Having two fxml files Frontpage.fxml and ConnectedPage.fxml with one controller projectxController i.e coded above
Frontpage.fxml has one button that will load connectedPage.fxml.
Connectedpage.fxml has one label
Now I want to set the Label text after connectedpage.fxml is loaded
public class ProjectX extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FrontPage.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setResizable(false);
stage.show();
}
When you create you fxml document you have to give a unique id for you Label:
The same you have done for the AnchorPane.
Example
#FXML
private Label myLabel;
Then inside the initialize method of your fxml controller class you can modify it as you want.
If you problem is how to access the Label from another controller you can use a get method or pass an instance of the controller you need . All that after the fxml has successfully loaded .
I recommend also that you use different controllers for different fxml files , cause it is more clear .
Have a search on fxml loading techniques and how to connect different controllers over the web and you will find what you need .
i'm trying to add an ActionListener to a label whitch pop out whenever user types wrong password or login.
Here is my Login Controller
public class LoginController implements Initializable {
#FXML
private Label label;
#FXML
private TextField LoginField;
#FXML
private PasswordField PasswdField;
#FXML
private Button LogInButton;
#FXML
private Label IncorrectDataLabel;
//private String uri = "http://google.com";
#FXML
private void LogIn(ActionEvent event) throws IOException {
if(LoginField.getText().equals("MKARK")&&PasswdField.getText().equals("KACZOR1"))
{
Parent parent = FXMLLoader.load(getClass().getResource("/fxmlFiles/MainScreen.fxml"));
Scene MainScene = new Scene(parent);
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
stage.setScene(MainScene);
stage.show();
}
else
{
IncorrectDataLabel.setVisible(true);
// <------------------- Here I want to bind hyperlink to a label with would open the google site, whenever user clicks it.
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
How am i able to fix that issue? I've tried many times (setOnAction, addMouseListener) but nothing worked :(.
If You dont mind i would also ask about the public void initialize function. What is it for? It pop out automatically when i created the class.
Thanks in advance
Labels do not fire action events. You could use a listener for mouse clicked events, e.g:
#FXML
private void gotoGoogle() {
// open url etc
}
and in the FXML file
<Label fx:id="IncorrectDataLabel" onMouseClicked="#gotoGoogle" ... />
However, it probably makes more sense to use a Hyperlink for this, which would give the user better visual feedback that it was something on which they were expected to click. Just replace the label with
<Hyperlink fx:id="IncorrectDataLabel" onAction="#gotoGoogle" text="..." ... />
and update the type in the controller accordingly:
#FXML
private Hyperlink IncorrectDataLabel ;
You need the appropriate import for javafx.control.Hyperlink in both the FXML file and in the controller.
Off-topic note: use proper Java naming conventions for your variable and method names.
like on Click for buttons , wanna do the the same thing for the load of my screen , i'am using scene builder.
Here is my code:
public class CModifierBoutique implements ControlledScreen{
#FXML
ChoiceBox<String> box;
ScreensController myController;
#Override
public void setScreenParent(ScreensController screenPage) {
myController = screenPage;
}
#FXML
private void goToMain(ActionEvent event){
myController.setScreen(ScreensFramework.screen1ID);
}
#FXML
private void inialize(ActionEvent event){
System.out.println(" there is the method who must be start on load this screen ");
System.out.println("my code is requesting the data base and the result");
System.out.println("will be added to my choisebox");
BoutiqueDao dao=new BoutiqueDao();
List<Boutique> li=dao.DisplayAll();
}
}
I think you are just looking for the initialize() method. Either your controller can implement the Initializable interface and do
public class CModifierBoutique implements ControlledScreen, Initializable {
// existing code..
#Override
public void initialize(URL location, ResourceBundle resources) {
// initialization code here...
}
}
or you can just include a no-argument method called initialize():
public class CModifierBoutique implements ControlledScreen {
// existing code..
public void initialize() {
// initialization code here...
}
}
Q: Help me identify what's causing the error, and hopefully getting the toolbar to work.
I'm trying to take the FXML-version from this page:
Difference in my java-class from link1:
It's not a main-class.
It does not extend Application but HBox or anything if it would work.
Error message: "javafx.fxml.LoadException: javafx.fxml.JavaFXBuilder$ObjectBuilder does not have a default property."
Well, here the class is:
public class MainWindow implements Initializable {
private ResourceBundle rb;
final static boolean RIGHT_TO_LEFT = false;
//FXML ATTRIBUTES
#FXML
private OverviewTab owContent;
#FXML
private StatisticsTab statisticsContent;
#FXML
private SettingsTab settingsContent;
#FXML
private Polygon dock_bottom;
#FXML
private TabPane tabpane;
#FXML
private Tab owTab;
#FXML
private Tab statisticsTab;
#FXML
private Tab settingsTab;
#FXML
private Button helpButton;
#FXML
private Button updateButton;
#FXML private Button task;
/**
* Create the application.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
this.rb = rb;
// Adding Swing style of custom Listener
tabpane.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>() {
#Override public void changed(ObservableValue<? extends Tab> observableValue, Tab oldTab, Tab newTab) {
if(newTab.equals(owTab)){
}
}
});
//statisticsContent.addListener(this);
owTab.setText(rb.getString("overviewTab_headline"));
statisticsTab.setText(rb.getString("statisticsTab_headline"));
settingsTab.setText(rb.getString("settingsTab_headline"));
}
}
The author of the tutorial you are referencing, mentions the error and provides solution to it in his next post/tutorial. See ToolBar in FXML No Longer Requires tag. I think you are facing the same problem.