JavaFX application with 2 or more fxml files - properties - java

I have an app with 3 fxml files.
The 1st is main window of app and most of work im doing here, but the 2 others fxml files allows me to change some settings and add more records to app.
I made it that 2 small fxml files extends the main file.
Basically:
public class FXMLDocumentController implements Initializable {
#FXML
private TextField txt;
#FXML
private Stage stage;
Symulacja symulacja = new Symulacja();
Promocja promocja = new Promocja();
#Override
public void initialize(URL url, ResourceBundle rb) {
txt.textProperty().bindBidirectional(promocja.getProgKwotyZetonow(), new NumberStringConverter());
labelProgKwotyZetonow.textProperty().bind(promocja.getProgKwotyZetonow().asString());
}
#FXML
public void zmienUstawienia() {
symulacja.zmienOkno("FXMLUstawienia.fxml", "Ustawienia");
}
#FXML
public void dodajKlientow() {
symulacja.zmienOkno("FXMLDodajKlienta.fxml", "Dodawanie");
}
}
It's main fxml Controller
public class FXMLUstawieniaController extends FXMLDocumentController{
#FXML
private TextField textProgKwota;
#FXML
private Button btnZatwierdzUstawienia;
#FXML
private TextField textProgIlosc;
#FXML
public void zatwierdzUstawienia() {
promocja.setProgIlosciZetonow(Integer.parseInt(textProgIlosc.getText()));
}
#Override
public void initialize(URL url, ResourceBundle rb) {
textProgKwota.textProperty().bindBidirectional(promocja.getProgKwotyZetonow(), new NumberStringConverter());
}
}
As you see I'm using properties to dynamically change what is showing in labelProgKwotyZetonow and textProgKwota.
When im not using the 2nd window txt and labelProgKwotyZetonow works fine, but when I'm initializing 2nd window I always get 0 in TextField and even if I change it this is not changing labelProgKwotyZetonow.
It's strange to me because when I'm souting (System.out.println) the value of promocja.getProgKwotyZetonow() in some places I get:
In function initialize in the 2nd controller - 0.
In function zmienUstawienia in 1st controller - the value from txt/labelProgKwotyZetonow.
In function zatwierdzUstawienia in 2nd controller - the value from textProgKwota.

Related

Thread for controlling components in JFXDrawer

I'm using a JFXDrawer, SalesDrawer containing a VBox and 2 JFXButtons inside it. The contents of the JFXDrawer have a separate controller, SalesDrawerController.java. The controller file, SalesController.java that contains the JFXDrawer consists of 2 anchor panes that I want to set visible on click of the buttons in the JFXDrawer. Till now I was using a set of static boolean variables and making sure on click of a button in the JFXDrawer one of the variables is set to true. Then in the SalesController.java, I used a TimerTask object to check which of these variables were true and set the needed anchor pane to visible. Is there a better way of doing this?
SalesDrawerController.java
public class SalesDrawerController implements Initializable {
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
#FXML
private void button1Hit(MouseEvent event) {
SalesController.SD[0]=true;
}
#FXML
private void button2Hit(MouseEvent event) {
SalesController.SD[1]=true;
}
}
SalesController.java
public class SalesController implements Initializable {
public static boolean SD[]= {false,false};
static boolean tock=true;
#FXML
private AnchorPane eq_newpane;
#FXML
private AnchorPane eq_delpane;
#FXML
private JFXHamburger SalesHam;
#FXML
private JFXDrawer SalesDraw;
public void initialize(URL url, ResourceBundle rb) {
eq_newpane.setVisible(true);
eq_delpane.setVisible(false);
eq_newpane.setDisable(false);
eq_delpane.setDisable(true);
VBox box = FXMLLoader.load(getClass().getResource("/fxml/SalesDrawer.fxml"));
SalesDraw.setSidePane(box);
HamburgerBackArrowBasicTransition transition = new HamburgerBackArrowBasicTransition(SalesHam);
transition.setRate(-1);
SalesHam.addEventHandler(MouseEvent.MOUSE_PRESSED,(e)->{
transition.setRate(transition.getRate()*-1);
transition.play();
if(SalesDraw.isShown()){
SalesDraw.close();
SalesDraw.toBack();
}
else{
SalesDraw.toFront();
SalesDraw.open();
}
});
threadtock();
}
public void threadtock() {
final java.util.Timer timer = new java.util.Timer();
final TimerTask delayedThreadStartTask;
delayedThreadStartTask = new TimerTask() {
public void run() {
try
{
if(tock){
if(SD[0])
{
eq_newpane.setVisible(true);
eq_delpane.setVisible(false);
eq_newpane.setDisable(false);
eq_delpane.setDisable(true);
}
else if(SD[1]){
eq_delpane.setVisible(true);
eq_newpane.setVisible(false);
eq_newpane.setDisable(true);
eq_delpane.setDisable(false);
}
if(tock)
{
threadtock();
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
};
timer.schedule(delayedThreadStartTask, 500);
};
}
Use synchronization mechanisms so you do not inherit deadlocks in your code from 2 or more threads attempting to operate on the same variable at once.
Figuring out how to properly synchronize your threads can be a pain, and it is very hard to explain, let alone debug. So, my best advice is to use google for "Java Concurrency" and "Java Thread Synchronization".
Otherwise, you should start a thread/threads from your main application to preform your intended operations

communication betwenn Tabs in JavaFx ans Scene builder

i made a mainEntredController which contains a TabPane with two tabs (HomeController) and (PatientController), The MainEntred Controle the Parameter Passage Between this two tabs but i have liitls issu that the tabs doesnet reconize the Parent (MainEntredController) or each other. it retuns an error inn this line
*** labelpatient.setText(mainec.LoadtxtFromlabelhometabhome()); ******
the idea is to get a text from the first tab to show it in a label in the second tab
hear's my code
the first is the MainEntred Class the Container
public class MainEntredController {
#FXML MenuItem closemi;
#FXML HomeController homecontroller;
#FXML PatientController patientcontroller;
public void initialize(URL location, ResourceBundle resources) {
System.out.println("Application Started");
homecontroller.intit(this);
patientcontroller.init(this);
}
public void ClickMenuItemClose(){
System.exit(0);
}
public String LoadtxtFromlabelhometabhome() {
// System.out.println(homecontroller.labelhome.getText());
return homecontroller.labelhome.getText();
}
public void setTabpatientlabel(String text) {
//patientcontroller.labelpatient.setText(text);
}
}
the Second is the First Tab HomeController
public class HomeController {
public MainEntredController mainec;
#FXML public Label labelhome;
#FXML private TextField tfhome;
#FXML private Button savehome;
#FXML private Button sendhome;
//public HomeController(){}
public void btnSaveHomeClicked(ActionEvent event){
System.out.println("le boutton save home est cliqué");
labelhome.setText(tfhome.getText());
}
public void btnSendHomeClicked(ActionEvent event){
System.out.println("le boutton send home est cliqué");
// send data to tab patient
mainec.setTabpatientlabel(labelhome.getText());
}
public void intit(MainEntredController mainEntredController) {
mainec = mainEntredController;
}
}
the Third one is the Second tab PatientController
public class PatientController {
public MainEntredController mainec;
#FXML public Label labelpatient;
#FXML private TextField tfpatient;
#FXML private Button savepatient;
#FXML private Button loadpatient;
public void btnSavePatientClicked(ActionEvent event){
System.out.println("le boutton save Patient est cliqué");
labelpatient.setText(tfpatient.getText());
}
public void btnLoadPatientClicked(ActionEvent event){
System.out.println("le boutton Load patient est cliqué");
labelpatient.setText(mainec.LoadtxtFromlabelhometabhome());
}
public void init(MainEntredController mainEntredController) {
mainec = mainEntredController;
}
}
And the FXML File of the MainEntred
<fx:include id="homecontroller" source="home.fxml" />
<fx:include id="patientcontroller" source="patient.fxml" />
i guess those two are madding the problem any advise how to solve it Please
i dont know why i am having java.lang.NullPointerException at the line declarred erlier he cant get the source (unknown source)
If i understand correctly then you want to communicate between controller. well, this can be done pretty easy.
in you main type something likes this:
FXMLLoader loader = new FXMLLoader(Main.class.getResource("your.fxml"));
Parent node = loader.load(); // this loads view
YourController instance = loader.getController();
some_class.initialize(instance);
Finelly i found what is wrong. the thing is that in the declaration in the MainController of the two Tabs we put the fx:id declared on the fxml file
and adding the word "Controller"
like this
#FXML private HomeController homeController;
#FXML private PatientController patientController;
the fx:id="home"
the second includes fx:id="patient"

How to set text of a TextArea in JavaFX from constructor?

I want to set a text in a TextArea from start in JavaFX, i use this code in constructor:
public class Myclass implements Initializable{
#FXML TextArea txta;
#FXML Button btn;
String msg;
Myclass(){
msg="Hello World";
txta.setText(msg);//This line is my setter.
}
#Override
public void initialize(URL location, ResourceBundle resources) {
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
msg=msg+"\nHallo Again!!");
txta.setText(msg);
}
});
}
Then the FXML doesn't show, but when i make comment the setter line, the FXML shows normally.
Please help, How can i fix this problem?
Your class is a controller, and it doesn't need a constructor. All the initial settings can be done in the initialize method. You can find here a basic tutorial.
Your text area txta will be properly initialized (that's why it has a #FXML annotation), so this will be enough:
public class Myclass implements Initializable{
#FXML private TextArea txta;
#FXML private Button btn;
private String msg;
#Override
public void initialize(URL url, ResourceBundle rb) {
msg="Hello World";
txta.setText(msg);
btn.setOnAction(e->{
msg=msg+"\nHallo Again!!";
txta.setText(msg);
});
}
}

Clear TextField From Another Class

In my main FXML controller class Alpha I have a mask with a text field and a button the clear it:
#FXML
private TextField testTF = new TextField();
#FXML
public void clearText() {
if (testTF != null)
testTF.clear();
}
If I enter text in to the text field and hit the clear button, the text is being removed. So far, all good.
I have a second controller class Beta. The corresponding fxml file contains the menu layout (menu bar). If the menu item "new" is clicked, it should also clear my text field in class Alpha.
public class Beta {
private void newApp() {
Alpha a = new Alpha();
a.clear();
}
}
Nothing happens though. What am I doing wrong here? How can I click a button/menu item in a FXML controller class and have it to clear a text field in another FXML controller class?
You should not instantiate testTF with new TextField();: FXMLLoader will automatically assign testTF the corresponding TextField object because you have a #FXML tag.
You're re-instantiating Alpha in class Beta, which exists separately from the one which was created when your fxml was loaded, resulting in two separate private TextField testTF objects. Either give Beta a reference to the first instance of Alpha, or try this alternative:
public class Alpha implements Initializable {
public static TextField tf;
#FXML
private TextField testTF;
#Override
public void initialize(URL location, ResourceBundle resources) {
tf = testTF;
}
}
public class Beta {
private void newApp() {
if (Alpha.tf != null)
Alpha.tf.clear();
}
}

Managing the runtime behavior of a JavaFX MenuBar

I have a BorderPane, onto which I placed a MenuBar. At the center of the BorderPane I display differnt AnchorPanes depending on the MenuItem selected. So far so good.
Now, how do I make sure that the Menus change behavior in response to the item selected in the child AnchorPane? So for example if the user selects "Edit", there will be a different action depending on whether the item currently higlighted is a user account, a file etc.
So far I made something along these lines:
The BorderPane controller:
public class MenuTest implements Initializable{
#FXML
private BorderPane borderPaneMain;
#FXML
private AnchorPane anchorPaneMain;
#FXML
private Menu menuEdit;
#FXML
private MenuItem itemEdit;
static String menuMode;
static String entityName;
public MenuTest(){
menuMode ="";
entityName = "";
}
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
AnchorPane anchor;
try {
anchor = (AnchorPane) new FXMLLoader().load(getClass().getResource("views/MainView.fxml"));
borderPaneMain.setCenter(anchor);
} catch (IOException e) {
e.printStackTrace();
}
}
protected static void setMenuMode(String menuMd, String entityNm){
entityName = entityNm;
menuMode = menuMd;
}
#FXML
private void onEditClick(){
if(entityName.equals(AnchorTest.FILE)){
//Launches correct edit view
new FXMLLoader().load(getClass().getResource("views/EditFile.fxml"));
//Passes the name of the entity so that the controller can retrieve its data
FileEditController.setFile(entityName);
}else if(entityName.equals(AnchorTest.PERSON)){
new FXMLLoader().load(getClass().getResource("views/EditPerson.fxml"));
PersonEditController.setFile(entityName);
}
}
}
The child AnchorPane controller:
public class AnchorTest implements Initializable{
public static final String PERSON = "PERSON";
public static final String FILE = "FILE";
ObservableList<String> peopleList;
ObservableList<String> fileList;
#FXML
private ListView<String> listPeople;
#FXML
private ListView<String> listFiles;
#Override
public void initialize(URL location, ResourceBundle resources) {
peopleList = FXCollections.observableArrayList("Frank","Matin","Anne");
fileList = FXCollections.observableArrayList("hello.txt","holiday.jpg","cv.doc");
listPeople.setItems(peopleList);
listFiles.setItems(fileList);
}
#FXML
private void personSelected(){
MenuTest.setMenuMode(this.PERSON, listPeople.getSelectionModel().getSelectedItem());
}
#FXML
private void fileSelected(){
MenuTest.setMenuMode(this.FILE, listFiles.getSelectionModel().getSelectedItem());
}
}
However I'm not sure that it's the best solution, especially considering the if/elseif statement will need to be altered whenever I add a new element type and its corresponding edit options. So is there any way that I can do this better?
I think if your application has only a few (2-4) different types of "things" that are represented by a AnchorPane, then your approach is totally fine. An alternative to your approach is the state pattern. In that case, your currently selected "item type" would be your state.

Categories

Resources