nested child call to super parent - javafx

i m new to javafx so please ignore my silly question here is problem i m facing from 2 day it would we great if any body help me
i have super parent (main view) in that country fxml view get loader
and in country fxml i have one more fxml(call table) that loaded into country
when user click on any data of table view new fxml file get loaded and that file i want to get load into parent i had used super parent stack pane id it throw an error please help me why this happening any solution link ,code or suggestion it will save my day
here is code
ObservableList<addcountryController> data = FXCollections.observableArrayList();
private Pagination pagination;
#FXML
private AnchorPane cresult;
#FXML
private StackPane stackconsearch;
#FXML
private StackPane stackhome;
#FXML
private AnchorPane stackanc;
#FXML
private StackPane stackcountry;
#FXML
private TableView<addcountryController> tableUser;
#FXML
private TableColumn<addcountryController, String> columnName;
#FXML
private TableColumn<addcountryController, String> columnDesc;
DatabaseHandler databaseHandler;
public void setText(String first,String sec){
this.country.setText(first);
this.desc.setText(sec);
}
#Override
public void initialize(URL location, ResourceBundle resources) {
databaseHandler = DatabaseHandler.getInstance();
initCol();
String qu = "SELECT * FROM country_tbl ";
ResultSet rs = databaseHandler.execQuery(qu);
try {
while (rs.next()) {
String id= rs.getString("id");
String name= rs.getString("countryname");
String description = rs.getString("descr");
String country2char= rs.getString("country2char");
String descrshort = rs.getString("descrshort");
data.add(new addcountryController(id,name, description,country2char,descrshort));
}
}catch (SQLException ex) {
Logger.getLogger(addcountryController.class.getName()).log(Level.SEVERE, null, ex);
}
tableUser.setItems(null);
tableUser.setItems(data);
tableUser.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
tableUser.getSelectionModel().getSelectedItems().addListener(new ListChangeListener<addcountryController>() {
public void onChanged(ListChangeListener.Change<? extends addcountryController> c) {
try {
Stage primaryStage=new Stage();
FXMLLoader loader =new FXMLLoader();
loader.load(getClass().getResource("/region/updatecountry.fxml").openStream());
updatecountryController usercontroller=(updatecountryController)loader.getController();
for (addcountryController p : c.getList()) {
String ADDID=p.getId();
String ADD=p.getName();
String ADD1=p.getDescriptionshort();
String ADD2=p.getDescription();
String ADD3=p.getCountrychar();
usercontroller.setText(ADDID,ADD,ADD1,ADD2,ADD3);
}
StackPane root = loader.getRoot();
stackconsearch.getChildren().clear();
stackconsearch.getChildren().add(root);
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
here is my editcontroller
private StackPane stackhome;
#FXML
private StackPane stackconsearch;
#FXML
private AnchorPane cresult;
#FXML
private TextField country;
#FXML
private TextField desc;
public void add(ActionEvent event) {
String ADD=countrycode.getText();
try {
if(ADD.isEmpty()){
Alert alert=new Alert(Alert.AlertType.ERROR);
alert.setHeaderText(null);
alert.setContentText("Please Fill All DATA");
alert.showAndWait();
return;
}
FXMLLoader loader =new FXMLLoader();
loader.load(getClass().getResource("/region/newCountry.fxml").openStream());
MainController usercontroller=(MainController)loader.getController();
usercontroller.setText(ADD);
StackPane root = loader.getRoot();
stackconsearch.getChildren().clear();
stackconsearch.getChildren().add(root);
}catch(Exception e) {
e.printStackTrace();
}
}
public void search(ActionEvent event) {
String countrytxt=country.getText();
String desctxt=desc.getText();
if(countrytxt.isEmpty() && desctxt.isEmpty()) {
try{
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.load(getClass().getResource("/region/cresult.fxml").openStream());
StackPane root = fxmlLoader.getRoot();
root.getStylesheets().add(getClass().getResource("/application/application.css").toExternalForm());
countryController usercontroller=(countryController)fxmlLoader.getController();
usercontroller.setText(countrytxt,desctxt);
cresult.getChildren().clear();
cresult.getChildren().add(root);
}catch(IOException e){
e.printStackTrace();
}
}else{
try{
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.load(getClass().getResource("/region/cresult.fxml").openStream());
StackPane root = fxmlLoader.getRoot();
countryController usercontroller=(countryController)fxmlLoader.getController();
usercontroller.setText(countrytxt,desctxt);
cresult.getChildren().clear();
cresult.getChildren().add(root);
}catch(IOException e){
e.printStackTrace();
}
}
}
here is main controller
#FXML
private StackPane stackhome;
#FXML
private AnchorPane Mainview;
#FXML
private AnchorPane stackanc;
#Override
public void start(Stage primaryStage) {
try {
Parent root =FXMLLoader.load(getClass().getResource("Main.fxml"));
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
#FXML
public void country(ActionEvent event) {
FXMLLoader fxmlLoader = new FXMLLoader();
try {
fxmlLoader.load(getClass().getResource("/region/country.fxml").openStream());
} catch (IOException e) {
}
StackPane root = fxmlLoader.getRoot();
stackhome.getChildren().clear();
stackhome.getChildren().add(root);
}
public static void main(String[] args) {
launch(args);
}
here is stackhome is super parent and stackcountry is parent and child of super parent and i have one more parent stacksub which is child of stackhome,stackcountry and it has child called as stackchild i want to load this stackchild to stackhome but it not working any suggestion

Related

JavaFX - How to switch to another tab with mouse click event [duplicate]

So I'm trying to load and save Images into an imageView where the location of the image is chosen through a file browser. I've been working on this for several days now and I'm gonna have a stroke if I can't get it fixed. I've tried everything I can think of. Thank you in advance for helping.
UPDATED:
Here is my main class:
public class Main extends Application {
private Stage primaryStage;
private BorderPane rootLayout;
public Main(){}
#Override
public void start(Stage primaryStage) throws Exception{
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Help Please");
initRootLayout();
showScreen();
}
public void initRootLayout(){
try{
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view/RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
RootLayout controller = loader.getController();
controller.setMain(this);
primaryStage.show();
}catch(Exception e ){e.printStackTrace();}
}
public void showScreen(){
try{FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view/sample.fxml"));
BorderPane sample = (BorderPane)loader.load();
rootLayout.setCenter(sample);
Controller controller = loader.getController();
controller.setMain(this);
}catch (Exception e){e.printStackTrace();}
}
public Stage getPrimaryStage(){return primaryStage;}
public static void main(String[] args) {
launch(args);
}
}
Here is the rootLayout:
public class RootLayout {
private Main main;
private Controller controller = new Controller();
public void setMain(Main main){this.main = main;}
#FXML
private void handleOpen(){
FileChooser fileChooser = new FileChooser();
FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter(
"PNG files (*.png)","*png");
fileChooser.getExtensionFilters().add(extensionFilter);
File file = fileChooser.showOpenDialog(main.getPrimaryStage());
if(file!= null){
controller.updateImage(file.toURI().toString());
}
}
}
And here is the controller:
public class Controller implements Initializable {
#FXML
ImageView imageView = new ImageView();
String imageURL;
Main main = new Main();
public void setMain(Main main){
this.main = main;
}
public void updateImage(String url){
if(url.length()>=1){
Image image = new Image(url);
imageView.setImage(image);
System.out.println(url);
}
else{
System.out.println(url);
System.out.println("image invalid");
}
}
#Override
public void initialize(URL location, ResourceBundle resources) {
}
}
Two things:
Never assign a field whose value is to be injected by an FXMLLoader (e.g. #FXML fields). Doing so is a waste of resources at best and introduces subtle bugs at worst. For instance, if you were to leave the imageView field uninitialized you'd be getting a NullPointerException which would indicate a problem with your setup. Since you do initialize the field, however, you don't get any errors and there's a false impression of the code working.
In your RootLayout controller class, you have:
private Controller controller = new Controller();
That instance of Controller you just created is not linked to any FXML file. And since you initialize the imageView field (see first point) you end up updating an ImageView which is not being displayed anywhere; this is where not initializing said field would have given a nice indication of there being a problem. The solution is to pass the Controller instance created by the FXMLLoader to the RootLayout instance created by the other FXMLLoader.
Also, in the same class you have:
Main main = new Main();
Which is also unnecessary since the created instance of Main is both not the correct instance and is replaced by the call to #setMain(Main) almost immediately.
Assuming your FXML files (which you did not provide) are correct, the Java classes should look more like:
Main.java
public class Main extends Application {
private Stage primaryStage;
private BorderPane rootLayout;
private RootLayout rootLayoutController;
public Main() {}
#Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Help Please");
initRootLayout();
showScreen();
}
public void initRootLayout() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view/RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
// store RootLayout instance in field so #showScreen()
// can reference it
rootLayoutController = loader.getController();
rootLayoutController.setMain(this);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public void showScreen() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view/sample.fxml"));
BorderPane sample = (BorderPane) loader.load();
rootLayout.setCenter(sample);
Controller controller = loader.getController();
controller.setMain(this);
// set Controller instance on RootLayout instance
rootLayoutController.setController(controller);
} catch (Exception e) {
e.printStackTrace();
}
}
public Stage getPrimaryStage() {
return primaryStage;
}
public static void main(String[] args) {
launch(args);
}
}
RootLayout.java
public class RootLayout {
private Main main;
private Controller controller;
public void setMain(Main main) {
this.main = main;
}
public void setController(Controller controller) {
this.controller = controller;
}
#FXML
private void handleOpen() {
FileChooser fileChooser = new FileChooser();
// Note extensions should be prefixed with "*."
FileChooser.ExtensionFilter extensionFilter =
new FileChooser.ExtensionFilter("PNG files (*.png)", "*.png");
fileChooser.getExtensionFilters().add(extensionFilter);
File file = fileChooser.showOpenDialog(main.getPrimaryStage());
if (file != null) {
controller.updateImage(file.toURI().toString());
}
}
}
Controller.java
public class Controller implements Initializable {
#FXML ImageView imageView; // leave uninitialized, will be injected
String imageURL;
Main main;
public void setMain(Main main) {
this.main = main;
}
public void updateImage(String url) {
if (url.length() >= 1) {
Image image = new Image(url);
imageView.setImage(image);
System.out.println(url);
} else {
System.out.println(url);
System.out.println("image invalid");
}
}
#Override
public void initialize(URL location, ResourceBundle resources) {}
}
Note: Did not test new code.

JavaFX run a method once a specified key is pressed

I am trying to run a method in a controller class specified to a particular task, once a specified key is pressed using KeyListener. But i'm unable to detect the keypress and invoke the java.awt.event keyPressed method. My code is as follows :
public class POSController implements KeyListener {
#Override
public void keyPressed(java.awt.event.KeyEvent e) {
if (e.getKeyCode() == com.sun.glass.events.KeyEvent.VK_F1) {
try {
paymentAction();
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
}
What could have gone wrong? Thanks in advance.
Here is the minimal executable example of the problem.
public class POSController implements KeyListener {
#FXML
private TableView<Product> productTableView;
#FXML
private TableView<Item> listTableView;
#FXML
private MenuItem logoutItem, profile;
#FXML
private javafx.scene.image.ImageView backImage;
#FXML
private MenuButton menuButton;
#FXML
private TableColumn<Item, String> itemColumn;
#FXML
private ComboBox<String> clientId, paymentMethod;
#FXML
private TableColumn<Item, Double> priceColumn, totalColumn, discountPercentageColumn, amountColumn;
#FXML
private TableColumn<Item, Integer> quantityColumn;
#FXML
private TableColumn<Product, String> productColumn;
#FXML
private TextField searchField,discountPercentage,productField,priceField,quantityField,vatPercentage,subTotalField,discountField,totalVatField,vatField,netPayableField,totalDiscountField;
#FXML
private TextField ;
#FXML
private TextField ;
#FXML
private TextField ;
#FXML
private TextField ;
#FXML
private TextArea descriptionArea;
#FXML
private Button addButton, removeButton, paymentButton, resetTableButton, resetButton;
#FXML
private Label quantityLabel, errorLabel, userName, backLabel;
#FXML
private ObservableList<Item> ITEMLIST;
public static Scene paymentScene;
private double xOffset = 0;
private double yOffset = 0;
public static double finalNetPayablePrice = 0.0;
public static double finalSubTotalPrice = 0.0;
public static double finalVat = 0.0;
public static double finalDiscount = 0.0;
public static String clientName = null;
public static String selectedPaymentMethod = null;
public static List<String> itemNames = new ArrayList<>();
public static List<Double> itemDiscounts = new ArrayList<>();
public static List<String> prices = new ArrayList<>();
public static List<String> quantities = new ArrayList<>();
public static List<String> subTotals = new ArrayList<>();
public static ObservableList<Item> itemList;
public static List<String> columnItemData = new ArrayList<>();
public static List<String> columnQuantityData = new ArrayList<>();
#FXML
private void initialize() throws SQLException, ClassNotFoundException, IOException {
ObservableList<Product> productsData = ProductDAO.searchGoodProducts(app.values.getProperty("STATUS_TYPE1"));
populateProducts(productsData);
}
#FXML
private void populateProducts(ObservableList<Product> productData) throws ClassNotFoundException {
productTableView.setItems(productData);
}
#Override
public void keyTyped(java.awt.event.KeyEvent e) {
}
#Override
public void keyPressed(java.awt.event.KeyEvent e) {
if (e.getKeyCode() == java.awt.event.KeyEvent.VK_F1) {
try {
paymentAction();
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
#Override
public void keyReleased(java.awt.event.KeyEvent e) {
}
#FXML
public void paymentAction() throws Exception {
if (validateInputsForPayment()) {
Payment payment = new Payment();
FXMLLoader loader = new FXMLLoader((getClass().getResource(app.values.getProperty("INVOICE_VIEW_LOCATION"))));
Parent root = loader.load();
Stage stage = new Stage();
root.setOnMousePressed((MouseEvent e) -> {
xOffset = e.getSceneX();
yOffset = e.getSceneY();
});
root.setOnMouseDragged((MouseEvent e) -> {
stage.setX(e.getScreenX() - xOffset);
stage.setY(e.getScreenY() - yOffset);
});
Scene scene = new Scene(root);
stage.initModality(Modality.APPLICATION_MODAL);
stage.initStyle(StageStyle.UNDECORATED);
stage.setScene(scene);
this.paymentScene = scene;
stage.showAndWait();
}
}
You shouldn't be using java.awt.event.KeyListener for a JavaFX application. JavaFX has its own set of event API.
Assuming that POSController is a controller class for a particular FXML:
public class POSController {
#FXML private BorderPane root; // Or any other Node from FXML file
#FXML private void initialize() {
javafx.event.EventHandler<javafx.scene.input.KeyEvent> handler = event -> {
if (event.getCode() == javafx.scene.input.KeyCode.F1) {
try {
paymentAction();
} catch (Exception e1) {
e1.printStackTrace();
}
}
};
// I'm using root to get scene, but any node would be fine
if (root.getScene() != null) {
root.getScene().addEventHandler(javafx.scene.input.KeyEvent.KEY_PRESSED, handler);
}
else {
root.sceneProperty().addListener((obs, oldScene, newScene) -> {
if (newScene != null) {
root.getScene().addEventHandler(javafx.scene.input.KeyEvent.KEY_PRESSED, handler);
}
});
}
}
}
This will add the key event to the Scene. If you do not need to apply this event scene-wide, then you can add the event handler at other appropriate nodes.
Update
If there are any input controls in the scene, then you may need to use setEventFilter() instead of setEventHandler(). This is because those controls are probably going to consume the key event during the event bubbling phase.

How to load image in ImageView dynamically in Java FX

I'm working with FXML and have two different Scene on a single Stage. btnStart is on scene1, and imgBtn is on scene2. When I click btnStart it sets scene2 to stage and loads an image to imageView (this is throwing NullPointerException). But when I click imgBtn on scene2 it is loading image.
My question is how to load image dynamically when I switch to scene2 ?
#FXML private Button imgBtn;
#FXML private Button btnStart;
#FXML public ImageView imageView;
#FXML
public void imgBtnClicked()throws Exception{
imageView.setImage(new Image(new FileInputStream("src/Assets/CardAssets/png-v2/3C.png")));
}
#FXML
public void btnStartClicked()throws Exception{
SetScene2();
imageView.setImage(new Image(new FileInputStream("src/Assets/CardAssets/png-v2/3C.png")));
}
public void SetScene2()throws Exception {
Parent root = FXMLLoader.load(getClass().getResource(fxmlFile2.fxml));
String css=getClass().getResource("myStyle.css").toExternalForm();
Scene scene;
try{
scene=new Scene(root,root.getScene().getWidth(),root.getScene().getHeight());
}
catch(NullPointerException e) {
scene=new Scene(root,stage.getWidth(),stage.getHeight());
}
scene.getStylesheets().add(css);
stage.setScene(scene);
}
The question is not exactly very clear, so I'm going to make some guesses here. The most likely problem is that you have confused which Nodes are on which scene which is on which controller.
The correct structure for this is that you have two sets of each of the following items:
FXML file
Controller class
Scene object.
This is how it should be done:
public class ControllerA {
#FXML private Button btnStart;
#FXML
public void btnStartClicked()throws Exception{
setScene2();
}
public void setScene2()throws Exception {
// You may need to set the controller to an instance of ControllerB,
// depending whether you have done so on the FXML.
Parent root = FXMLLoader.load(getClass().getResource(fxmlFile2.fxml));
String css=getClass().getResource("myStyle.css").toExternalForm();
Scene scene;
try{
scene=new Scene(root,root.getScene().getWidth(),root.getScene().getHeight());
}
catch(NullPointerException e) {
scene=new Scene(root,stage.getWidth(),stage.getHeight());
}
scene.getStylesheets().add(css);
stage.setScene(scene);
}
}
public class ControllerB {
#FXML private ImageView imageView;
#FXML private Button imgBtn;
#FXML public void initialize() {
imageView.setImage(new Image(new FileInputStream("src/Assets/CardAssets/png-v2/3C.png")));
}
#FXML
public void imgBtnClicked()throws Exception{
imageView.setImage(new Image(new FileInputStream("src/Assets/CardAssets/png-v2/3C.png")));
}
}

JavaFX change ComboBox items (outside of initialize() method)

I am playing around with SceneBuilder and come across a few questions about the intialize() method and how to change ComboBox items after it's already been initialized in said method. So basically, after I set the items in initialize, I am not able to change them anymore from another method in the controller.
Here is my code:
public class AppController implements Initializable {
private ObservableList<String> list = FXCollections.observableArrayList();
private MainModel model;
#FXML
private ComboBox<String> cobUsers = new ComboBox<String>();
#Override
public void initialize(URL url, ResourceBundle rb) {
list.add("name1");
list.add("name2");
cobUsers.setItems(list); // this works!
}
public void initModel(MainModel model) {
this.model = model;
}
public void addItems(){
list.add("name3");
list.add("name4");
cobUsers.setItems(list); // this does not work. ComboBox items remain "name1" and "name2"
}
}
public class App extends Application {
private Stage primaryStage;
private AnchorPane rootLayout;
private AppController appController = new AppController();
MainModel model = new MainModel();
#Override
public void start(Stage primaryStage) {
appController.initModel(model);
this.primaryStage = primaryStage;
this.primaryStage.setTitle("App");
initRootLayout();
appController.addItems();
}
/**
* Initializes the root layout.
*/
public void initRootLayout() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("FXMLDocument.fxml"));
rootLayout = (AnchorPane) loader.load();
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
So guess my question is, how can I access/change my ComboBox later on, after it's been initialized in intialize()?
Thanks! :)
UPDATE 1:
I have changed the initRootLayout() in the App class (see below) and it WORKS now. list now contains 4 items and all of them show up in the ComboBox after calling addItems(). Thanks everyone!
public void initRootLayout() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader(); loader.setLocation(getClass().getResource("FXMLDocument.fxml"));
rootLayout = (AnchorPane) loader.load();
AppController controller = loader.<AppController>getController();
controller.addItems();
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}

Switching scenes in JavaFX dynamically

I want to switch between 2 different scenes:
Scene 1: ScrollPane where I load different images.
Scene 2: the stage is transparent and there's only 1 button to return to Scene 1.
I´ve been able to do it just having a different fxml for each scene and creating a new scene every time I switch them.
The problem is when I switch from scene 2 to scene 1, all the images loaded in scene 1 aren't there (It´s obvious as I´m creating a new scene rather than "loading" Scene1.
Is there any way to keep the images already loaded when I swith from Scene 2 to Scene 1?
Scene1
public class ControllerImpl implements Initializable, ControlledScreen {
ScreensController myController;
public void initialize(URL url, ResourceBundle rb) {
}
public void setScreenParent(ScreensController screenParent){
myController = screenParent;
}
#FXML
private void goToScreen2(ActionEvent event) throws Exception{
try {
Stage primaryStage = (Stage) hideStage.getScene().getWindow();
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/arrow.fxml"));
Parent root1 = fxmlLoader.load();
primaryStage.setScene(new Scene(root));
}
catch (Exception e) {
e.printStackTrace();
}
}
#FXML
public javafx.scene.control.Button hideStage;
}
Scene2:
public class ControllerArrow implements Initializable{
ScreensController myController;
#Override
public void initialize(URL url, ResourceBundle rb) {
}
public void setScreenParent(ScreensController screenParent){
myController = screenParent;
}
#FXML
public javafx.scene.control.Button showStage;
#FXML
private void goToScreen1(ActionEvent event) throws Exception{
try{
Stage stage = (Stage) showStage.getScene().getWindow();
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/sample.fxml"));
Parent root = fxmlLoader.load();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
You can switch the scene of your stage like:
Stage stage = (Stage) scene.getWindow();
stage.setScene(yourScene);
So when you have an instance of your scene, you can apply it to your stage

Resources