How to load image in ImageView dynamically in Java FX - javafx

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")));
}
}

Related

JavaFX BorderPane

i'm trying to set on top of a borderpane an fxml hbox, the borderpane is inside another borderpane that contains all.
The containers are in this form:
Stage-> PincipalBorderPane -> Vbox(Center of MainMenuBorderPane)-> ContentBorderPane(in bottom of Vbox).
Also in the left of my PrincipalBorderPane, I have a sidebar menu that contains buttons, I want to set on the top of ContentBorderPane an fxml document that will be like an small menu to show buttons that would set on the bottom of ContentMenu different panes. The problem is that I don't know how to set an fxml to a borderpane that is inside another borderpane.
public class MenuContentController implements Initializable {
private boolean flag = true;
private boolean flagsc = true;
#FXML
private JFXButton Minbtn;
#FXML
private JFXButton Maxbtn;
#FXML
private JFXButton Closebtn;
#FXML
private JFXButton Sidebarbtn;
#FXML
private JFXTextField Searchtxt;
#FXML
private JFXButton Ingressbtn;
#FXML
private JFXButton Egressbtn;
#FXML
private JFXButton Statusbtn;
#FXML
private BorderPane ContentTools;
#FXML
private void open_sidebar(ActionEvent event) throws IOException {
BorderPane border_pane = (BorderPane) ((Node) event.getSource()).getScene().getRoot();
if (flag) {
//Revisar animación más adelante
Parent sidebar = FXMLLoader.load(getClass().getResource("/app/fxml/Sidebar.fxml"));
sidebar.translateXProperty();
//
border_pane.setLeft(sidebar);
//
Timeline timeline = new Timeline();
KeyValue kv = new KeyValue(sidebar.translateXProperty(),0,Interpolator.EASE_IN);
KeyFrame kf = new KeyFrame(Duration.seconds(10), kv);
timeline.getKeyFrames().add(kf);
timeline.play();
flag = false;
} else {
border_pane.setLeft(null);
flag = true;
}
}
**#FXML
public void open_admintools_priv(ActionEvent event) throws IOException{
ContentTools = new BorderPane();
BorderPane bp = (BorderPane) ContentTools;
if (flagsc) {
Parent admintools = FXMLLoader.load(getClass().getResource("/app/fxml/AdminTools.fxml"));
bp.setTop(admintools);
flagsc=false;
} else {
ContentTools.setTop(null);
flagsc = true;
}
System.out.println(flagsc);**
}
The method open_admintools_priv should to set visible on top of ContentTools(ContentBorderpane) the Admintools.fxml by pressing a button in another fxml(sidebar.fxml) that I set on the left of my PrincipalBorderPane with the method open_sidebar, that I call creating a new controller of MenuContentController in the SidebarController:
public class SidebarController implements Initializable {
private boolean flagsc = true;
#FXML
private JFXButton condominiobtn;
#FXML
private JFXButton adminbtn;
#FXML
private JFXButton finanzasbtn;
#FXML
private JFXButton reportesbtn;
#FXML
private JFXButton confbtn;
#FXML
private void open_admintools(ActionEvent event) throws IOException{
MenuContentController aux = new MenuContentController();
aux.open_admintools_priv(event);
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
Another problem is that by this way, at the moment I create a MenuContentController, the variable flag is always on true, this variable I use it to set the fxml in borderpane when flag is true, or quit it when flag is false. I don't know if creating an instance of a controller is the way to acces to the objects of that fxml, thanks for your time.

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(FXML) error

So, I'm trying to switch scenes in JavaFX but I can't seem to get it to work when I hard coded it I was able to get it working by using lambda expressions.
public class Main extends Application {
Stage window;
Scene scene1;
Scene scene2;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
window = primaryStage;
Label label = new Label("Welcome to the first scene");
Button bttn1 = new Button("Go to second scene");
bttn1.setOnAction(e -> window.setScene(scene2));
//Scene 1
VBox layout1 = new VBox(20);
layout1.getChildren().addAll(label, bttn1);
scene1 = new Scene(layout1, 400, 400);
//Scene 2
Button bttn2 = new Button("Go to first scene");
bttn2.setOnAction(e -> window.setScene(scene1));
StackPane layout2 = new StackPane();
layout2.getChildren().add(bttn2);
scene2 = new Scene(layout2, 400, 500);
window.setScene(scene1);
window.setTitle("Test");
window.show();
}
However the project involves a few different GUIs and I would prefer to design the GUI's in FXML Scene Builder than to hardcode them the FX way. However when I have tried to do the FXML way it hasn't worked an error is always appearing when I press the button.
Error message
This is the document controller code.
public class FXMLDocumentController implements Initializable {
#FXML
private Button button1;
#FXML
private Button button2;
#FXML
private void handleButtonAction(ActionEvent event) throws IOException {
Stage stage;
Parent root;
if(event.getSource() == button1){
stage=(Stage)button1.getScene().getWindow();
root = FXMLLoader.load(getClass().getResource("FXML2.fxml"));
}
else{
stage=(Stage)button2.getScene().getWindow();
root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
}
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
The error you posted says the code is trying to load a button as an anchor pane. Check too see if you have an anchorpane with the fx:I'd of button1.

nested child call to super parent

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

Close the login page in javafx when open a new stage

Hi I am creating a login page and a dashboard page I want to close or hide my login page and Show Dashboard When I Click on Login Button. but its not working
public class LoginController implements Initializable {
#FXML
private TextField txtUser;
#FXML
private PasswordField txtPassword;
#FXML
private Label message;
#FXML
private Label lblUser;
#FXML
private Label lblPassword;
#FXML
private void OpenDashBoard(ActionEvent event) {
try {
FxmlMethods object = new FxmlMethods();
// showFxml method usd for open a new window named DashBoard.fxml
object.showFxml("/DashBoard/DashBoard.fxml", "/ DashBoard/DashboardStyle.css", "Dash Board");
} catch (Exception exception) {
exception.printStackTrace();
}
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
And My Main Class is :
public class DATACOLLECTION extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Login.fxml"));
stage.getIcons().add(new Image("/images/icon.png"));
Scene scene = new Scene(root);
stage.setTitle("Login");
stage.setScene(scene);
scene.getStylesheets().addAll(this.getClass().getResource("Login.css").toExternalForm());
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
please help me
I am using this and its working Thanks to all for your Response.
#FXML
private void CloseAction(ActionEvent event) {
Stage stage = (Stage) Close.getScene().getWindow();
stage.close();
}

Resources