Hello I need to pass The User and Pass Values to another Controller:
like this AdminController ->UserController.
In my code I have This in AdminController:
private TextField fusuario;
#FXML
private PasswordField fcontrasena;
String a;
String b;
public void captura() {
a=fusuario.getText().toString();
System.out.println("el usuario es x:"+a);
b=fcontrasena.getText().toString();
System.out.println("la contraseƱa es x:"+b);
}
public String setFusuario(String a) {
this.fusuario.setText(a);
return a;
}
public String setFcontrasena(String b) {
this.fcontrasena.setText(b);
return b;
}
This is in my UserController:
Stage administrador=new Stage();
FXMLLoader carga = new FXMLLoader(getClass().getResource("Admin.fxml"));
Parent StackPane =(Parent) carga.load();
AdminScreenController control = carga.<AdminScreenController>getController();
control.deshabilitarespuesta();
Scene scene = new Scene(StackPane);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
administrador.setScene(scene);
administrador.setTitle("AdminScreen");
Stage userstage=(Stage)comentarios.getScene().getWindow();
userstage.hide();
administrador.show();
How i Pass this Values, some help or orientation?
This is easy you need to declare a static variable like this in the FIRST Controller
static String alertTYPE;
Then in our ERROR checking code we give alertTYPE a value
if(txtAmount.getLength() == 0){
alertTYPE = "1";
customAlert();
txtAmount.requestFocus();
return;
}
Now we call customAlert() method still in the same Controller class
Her is the customAlert method code
public void customAlert() throws IOException{
// This method displays the MODAL Alert alert.fxml and it is controlled by AlertController
// =========================================================================================
alertPane = FXMLLoader.load(getClass().getResource("alert.fxml"));// pane you are GOING TO
//Scene Sscene = new Scene(merrorPane, 600, 400);
// NO NEED TO RE-SIZE but this is code to change size
Scene Mscene = new Scene(alertPane);
Mstage = new Stage();
Mstage.initStyle(StageStyle.UNDECORATED);
Mstage.setResizable(false);
Mstage.initModality(Modality.APPLICATION_MODAL);
Mstage.setScene(Mscene);
Mstage.showAndWait();
}
Here in the AlertController we make use of the alertTYPE value
#Override
public void initialize(URL url, ResourceBundle rb) {
if(alertTYPE.equals("1")){
lblMessage.setText("Enter "+type+" Amount");
}else if(alertTYPE.equals("2")){
You need to be sure the Controller you are going to imports the static variable alertTYPE like this
import static checkbook.CBManagerController.alertTYPE;
This was a long way around but we hope you get the idea
One word of caution once static variables are declared and given a value that value is retained until a new value is given to the variable or you set it to nothing like this for a String alertTYPE = ""; With great power comes great responsibility ha ha
Related
maybe someone will explain. I have a method, that sets label text if login is successful.
#FXML
private void loginUser(ActionEvent event) throws IOException {
String user = username.getText();
String pass = password.getText();
if(validateFields(user, pass) && validateLogin(user, pass)) {
welcome.setText("Welcome, " + globalUser.getUserName()); //works
infoLine.setText("Redirecting to main dashboard..."); //works
}
}
And if I add additional code, which changes the scene after login, the label text is not changing:
#FXML
private void loginUser(ActionEvent event) throws IOException {
String user = username.getText();
String pass = password.getText();
if(validateFields(user, pass) && validateLogin(user, pass)) {
welcome.setText("Welcome, " + CurrentUser.getCurrentUser().getUserName());//not working
infoLine.setText("Redirecting to main dashboard..."); //not working
//Changing scene after successful login
Parent home = FXMLLoader.load(getClass().getResource(ScenePath.HOME.getPath()));
Scene homeScene = new Scene(home);
Stage appStage = (Stage) ((Node) event.getSource()).getScene().getWindow();
appStage.setScene(homeScene);
appStage.show();
}
}
How to solve this problem?
My controller class looks like this. Nothing special. After 2 validations it set texts of labels and changes scenes.
public class LoginController {
#FXML
private TextField username;
#FXML
private PasswordField password;
#FXML
private Label infoLine;
#FXML
private Label welcome;
#FXML
private Button exitBtn;
UserDao userDao = new UserDao();
#FXML
private void initialize() {
close();
}
#FXML
private void loginUser(ActionEvent event) throws IOException {
String user = username.getText();
String pass = password.getText();
if(validateFields(user, pass) && validateLogin(user, pass)) {
welcome.setText("Welcome, " + CurrentUser.getCurrentUser().getUserName());
infoLine.setText("Redirecting to main dashboard...");
//Changing scene after successful login
Parent home = FXMLLoader.load(getClass().getResource(ScenePath.HOME.getPath()));
Scene homeScene = new Scene(home);
Stage appStage = (Stage) ((Node) event.getSource()).getScene().getWindow();
appStage.setScene(homeScene);
appStage.show();
}
}
private boolean validateFields(String userName, String password) {
if (userName.isEmpty() || password.isEmpty()) {
infoLine.setText("Username and password can't be empty!");
return false;
}
return true;
}
private synchronized boolean validateLogin(String userName, String password) {
User user = userDao.getConnectedUser(userName, password);
if (user == null) {
infoLine.setText("User not found!");
return false;
}
CurrentUser.setCurrentUser(user);
return true;
}
private void close() {
exitBtn.setOnAction(SceneController::close);
}
}
Basically, the text is changing. The problem is as soon as the text is changed, you load the next view. This is happening really fast. The solution is to slow things down. Mainly, give the user time to see the text change before loading the new view. This can be done using PauseTransition.
After the text change, try the following code. After the text changes, this code gives a two-second delay before loading the new view.
PauseTransition pause = new PauseTransition(Duration.seconds(2));
pause.setOnFinished(
e -> {
Parent home = FXMLLoader.load(getClass().getResource(ScenePath.HOME.getPath()));
Scene homeScene = new Scene(home);
Stage appStage = (Stage) ((Node) event.getSource()).getScene().getWindow();
appStage.setScene(homeScene);
appStage.show();
}
);
pause.play();
apologies for the length of my code. I realized last night that I was on the wrong path and now have gotten stuck on an issue that I think relates to JavaFX event handling. Initially I had the logic functioning outside a GUI in a basic loop that depended on interaction through the console. Everything was working great. I've now tried to get this to work in a GUI with interaction from the user.
I have two main problems with the code below.
The first is that the text in textArea is not updating with additional text after the startButton executes the start of my main logic sequence. The first append starts right under the first while loop. I was hoping to have this show up in the GUI as the logic executes. I'm not sure if I need to tell the GUI to update at certain intervals or if there's something else wrong.
Second, I'm not sure how to get the program to wait for the user to type in something into textField before hitting the textButton I created to continue on. I used to have a scanner created which caused the program to wait in the console for input. I realize I need some way of telling it to wait for a button press when it's running inside JavaFX.
I chose not to include the rest of the code to make things easier to read, but I can add it on if it will help resolve this issue.
Thank you everyone for your help!
public class FxApp extends Application {
//Creates FileParser object with methods that alter the incoming Array of Strings into the format we need
FileParser fileParser = new FileParser();
Configure configure = new Configure();
private String text;
private String initialState;
private ArrayList<Machine> machines = new ArrayList<Machine>();
private Map<String, String> initialStates = new HashMap<String, String>();
private Map<String, String> states = new HashMap<String, String>();
private Map<String, ArrayDeque<String>> queues = new HashMap<String, ArrayDeque<String>>();
private Map<Integer, ArrayList<String>> parsedData = new HashMap<Integer, ArrayList<String>>();
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("File Chooser");
FileChooser fileChooser = new FileChooser();
fileChooser.getExtensionFilters().addAll(new ExtensionFilter("Text Files", "*.txt"));
Button startButton = new Button("Start");
Button openButton = new Button("Click to open a file...");
openButton.setPrefSize(200, 80);
Button textButton = new Button("Enter");
TextArea textArea = new TextArea();
textArea.setWrapText(true);
TextField textField = new TextField();
Label lbl = new Label();
VBox vbox = new VBox(lbl, openButton, startButton, textArea, textField, textButton);
vbox.setSpacing(10);
vbox.setPadding(new Insets(15));
lbl.setText("This tool creates virtual automata based \ron the file.");
Scene scene = new Scene(vbox, 640, 480);
primaryStage.setScene(scene);
primaryStage.show();
openButton.setOnAction(
new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
File file = fileChooser.showOpenDialog(primaryStage);
if (file != null) {
//Execute the method to convert to string array before sending to file parser
try {
fileParser.convertFile(file);
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
});
textButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
text = textField.getText();
}
});
startButton.setOnAction(new EventHandler <ActionEvent>()
{
public void handle(ActionEvent event)
{
machineCreation();
String exit = "no";
String nextLine = null;
ArrayList<String> listOfCurrentTransitions = new ArrayList<String>();
int nextInt = 0;
states = initialStates;
while(!(exit.toLowerCase().equals("yes"))) {
textArea.appendText("Choose a state to load");
//Print out the states possible for each machine
ArrayList<String> tempTrans = machines.get(nextInt).getTransitions();
//This loops through the list of transitions of the machine and pulls possible transitions from its current state
for(int i = 0; i < tempTrans.size(); i++) {
String pull = tempTrans.get(i);
String[] apart = pull.split(" ");
pull = apart[0];
if(states.get(Integer.toString(nextInt)).equals(pull)) {
listOfCurrentTransitions.add(tempTrans.get(i));
}
}
if(!(listOfCurrentTransitions.isEmpty())) {
textArea.appendText("The following transitions are possible. Choose one: " + listOfCurrentTransitions);
}
else {
textArea.appendText("No transitions for this machine exist from its current state");
}
//Tell GUI to wait for user input in textField and execute textButton which assigns to String text. Resume on button click.
The while loop blocks the JavaFX application thread which prevents updates of the GUI and handling of events.
You need to execute the logic of a single iteration of the loop on each "text commit" instead:
private TextArea textArea;
private void activateState(int nextInt) {
ArrayList<String> listOfCurrentTransitions = new ArrayList<String>();
textArea.appendText("Choose a state to load");
//Print out the states possible for each machine
ArrayList<String> tempTrans = machines.get(nextInt).getTransitions();
//This loops through the list of transitions of the machine and pulls possible transitions from its current state
for(int i = 0; i < tempTrans.size(); i++) {
String pull = tempTrans.get(i);
String[] apart = pull.split(" ");
pull = apart[0];
if(states.get(Integer.toString(nextInt)).equals(pull)) {
listOfCurrentTransitions.add(tempTrans.get(i));
}
}
if(listOfCurrentTransitions.isEmpty()) {
textArea.appendText("No transitions for this machine exist from its current state");
} else {
textArea.appendText("The following transitions are possible. Choose one: " + listOfCurrentTransitions);
}
}
#Override
public void start(Stage primaryStage) throws Exception {
...
textArea = new TextArea();
...
startButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
machineCreation();
activateState(0);
}
});
textButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
// read input and ask for more input...
int nextState = Integer.parseInt(textField.getText()); // TODO: deal with invalid input
activateState(nextState);
}
});
You probably need to fix the logic a bit to verify a transition is valid, change the values of some fields ect...
My program is structured package as follows
-Browser.fxml
-Elements.fxml
+BrowserController : Browser transmit values url to Elements
#FXML
void txtURL(ActionEvent event) {
Pane pnLoad = fxmlLoader.load(getClass().getResource("Elements.fxml").openStream());
FunctionController controller = (FunctionController) fxmlLoader.getController();
controller.viewURL(txtURL.getText());
}
+ElementsController :,
-With reading after I can only use the value url once for function viewURL
#FXML
public void viewURL(String url) {
System.out.println(url);
}
+How can I use the url again?
#FXML
void btnReviewUrl(ActionEvent event) {
System.out.println(url);
}
Please help me!
You can create a Static variable in your class and assign the url value to that variable to ve used again anf across classes
public static String urlValue;
#FXML
public void viewURL(String url) {
System.out.println(url);
urlValue = url;
}
I have written a controller for two windows /stages.
The first window is opened in the MainClass. The second in the Controller, if the user clicks onto a button.
How can I get the TextFields from second.fxml in the applyFor()-method?
Thanks.
#FXML
protected void requestNewAccount(ActionEvent event) {
try {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("second.fxml")); // TextFields in there
Parent root = (Parent) fxmlLoader.load();
Stage stage = new Stage();
stage.initModality(Modality.APPLICATION_MODAL);
stage.setTitle("Second Window");
Scene scene = new Scene(root);
String css = MainOnlineCustomer.class.getResource("/style.css").toExternalForm();
scene.getStylesheets().clear();
scene.getStylesheets().add(css);
stage.setScene(scene);
stage.show();
} catch (IOException e) {
logger.error(e);
}
}
/**
* closes the "second"-Window
* #param event
*/
#FXML
protected void cancel(ActionEvent event) {
final Node source = (Node) event.getSource();
final Stage stage = (Stage) source.getScene().getWindow();
stage.close();
}
#FXML
protected void applyFor(ActionEvent event) {
// get values from TextField in second.fxml here!!!
}
It's not good to share controllers between fxmls unless they serve the same purpose. Here both fxml seem to serve a different purpose (account management, login or something similar for one of them and creating a new account for the other). What is even worse is that those classes do not share the same controller instance, which means the small (and probably only) benefit you could get from using the same controller, is not used here. You should better use different controllers.
Since you use Modality.APPLICATION_MODAL as modality, I'd recommend using showAndWait instead of show to open the new stage. This will enter a nested event loop, which allows the UI to remain responsive and continues after the invocation of showAndWait once the stage is closed.
Furthermore add a method to the controller of second.fxml that allows you to retrieve the result.
Example
This creates a Person object with given name and family name.
"primary window (opening the "inner" stage)
FXMLLoader loader = new FXMLLoader(getClass().getResource("second.fxml"));
Stage subStage = new Stage();
subStage.initModality(Modality.APPLICATION_MODAL);
subStage.setTitle("Second Window");
Scene scene = new Scene(loader.load());
subStage.setScene(scene);
subStage.showAndWait();
Optional<Person> result = loader.<Supplier<Optional<Person>>>getController().get();
if (result.isPresent()) {
// do something with the result
}
controller for "inner" content
public class SecondController implements Supplier<Optional<Person>> {
#FXML
private TextField givenName;
#FXML
private TextField familyName;
private boolean submitted = false;
// handler for submit action
#FXML
private void submit() {
submitted = true;
givenName.getScene().getWindow().hide();
}
// handler for cancel action
#FXML
private void cancel() {
givenName.getScene().getWindow().hide();
}
#Override
public Optional<Person> get() {
return submitted ? Optional.of(new Person(givenName.getText(), familyName.getText())) : Optional.empty();
}
}
Note that you can gain access to any data available to the controller this way. I wouldn't recommend accessing any nodes (like TextFields) directly though, since this makes changing the UI harder.
Using the Supplier interface here is not necessary, but I chose to do this to achieve a loose coupling between SecondController and the main window.
I am trying to make a browser using javafx in which i want to add the bookmark functionality.I want to bookmark the webpage and display it in the menuitem.Bookmarking is working but the problem is that it is not displaying the bookmark field in the menuitem.I try to print the value in the console it is printing the value in the console but it is not displaying in the menuitem.
Now ,FirstpageController is the main controller whose fxml file is "Firstpage.fxml".This fxml only contain a tabpane.It contain an included file that is TabpageController which contains following code:
TabpageController contains a button "bookmark_btn" which is used to add bookmark in the browser using addbookmark() method.It's fxml file is "Tabpage.fxml" which is included in "Firstpage.fxml".
TabpageController.java
public class TabpageController implements Initializable
{
#FXML public TextField addressField;
#FXML private Button bookmark_btn;
#FXML private Menu bookmenu;
#FXML public MenuItem bkmenuitem;
#FXML
private void addbookmark() throws IOException
{
Bookmodel bm = new Bookmodel(addressField.getText(), first.tab1.getText()); //Take the url and tile
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("/tabcheck/Bookmarkpage.fxml"));
AnchorPane bookmarkpane = loader.load();
Stage bookstage = new Stage();
bookstage.setResizable(false);
bookstage.show();
Scene bookscene = new Scene(bookmarkpane);
bookstage.setScene(bookscene);
Bookmarkcontroller bc = loader.getController();
bc.setBookinfo(bm);
//bkmenuitem.setText(DEFAULT_HOME.toString());
}
public void setBookinfo(Bookmodel bookinfo)
{
System.out.println("setbookinfo enetring for add btn");
bkmenuitem.setText(bookinfo.getTitile());
System.out.println(bookinfo.getTitile());
System.out.println(bkmenuitem.getText());
System.out.println("setbookinfo");
this.bookinfo = bookinfo;
}
Now by clicking on "bookmark_btn" it open new scene that is "Bookmarkpage.fxml" which a simple bookmarking window which contain 2 textfield for url,title and "add" button.Now by clicking on "Add" button it should bookmark the current page.There is the menu "bookmenu" in the "tabpage.fxml" which contain menuitem "bkmenuitem".All the bookmark field should be display in the menuitem "bkmenuitem" which is in the "tabpage.fxml" file.
Also the controller of this "Bookmarkpage.fxml" is "Bookmarkcontroller.java" which contain following code:
Bookmarkcontroller.java
public class Bookmarkcontroller {
#FXML
TextField bookmarkTitleTextField;
#FXML
TextField bookmarkURLTextField;
#FXML private Button addbook;
TabpageController tabpageController;
private Bookmodel bookinfo;
#FXML private void BookmarkToModelActionEvent(ActionEvent event) throws IOException
{
((Node) event.getSource()).getScene().getWindow().hide();
Bookmodel addbm = new Bookmodel(bookmarkTitleTextField.getText());
System.out.println(bookmarkTitleTextField.getText());
System.out.println("add to menuitems");
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("/tabcheck/Tabpage.fxml"));
AnchorPane bookmarkpane = loader.load();
TabpageController addtc = loader.getController();
addtc.setBookinfo(addbm);
//bkmenuitem.setText(bookmarkTitleTextField.getText());
}
public void setBookinfo(Bookmodel bookinfo) {
bookmarkURLTextField.setText(bookinfo.getUrl());
bookmarkTitleTextField.setText(bookinfo.getTitile());
this.bookinfo = bookinfo;
}
This the model class of the "Bookmarkcontroller"
Bookmodel.java
public class Bookmodel {
private String url;
private String titile;
public Bookmodel() {
}
public Bookmodel(String url, String titile) {
this.url = url;
this.titile = titile;
}
public Bookmodel(String titile) {
this.titile = titile;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getTitile() {
return titile;
}
public void setTitile(String titile) {
this.titile = titile;
}
}
Output from Bookmarkcontroller.java
google
add to menuitems
Output from TabpageController.java
setbookinfo enetring for add btn
google
google
setbookinfo
As it is printing the output of these 2 lines as"google"
System.out.println(bookinfo.getTitile());
System.out.println(bkmenuitem.getText());
but not showing anything in the menuitem field for following line...
bkmenuitem.setText(bookinfo.getTitile());
I try a lot and also check it on stackoverflow on how to pass parameter from one controller to another but nothing is working.Also I am not getting any error.But the menuitem "bkmenuitem " is not printing the value.Any help would be appreciated as i am struggling a lot sorry for the long code .If i don't provide this much code then i won't understand anything.
I was able to get this to work by changing the TabpageController addbookmark method to
FXMLLoader loader = new FXMLLoader();
loader.setLocation( ....);
loader.load();
AnchorPane bookmarkpane = loader.getRoot();
Bookmarkcontroller bc = loader.getController();
Stage bookstage = new Stage();
bookstage.setResizable(false);
Scene bookscene = new Scene(bookmarkpane);
bookstage.setScene(bookscene);
bookstage.show();
bc.setMenuItem(bkmenuitem);
bc.setBookinfo(bm);
showing the stage after scene is added and passing thru the menuitem then
in Bookmarkcontroller creating a setter for the menu item and updating it
MenuItem menuitem;
public void setMenuItem(MenuItem bkmenuitem)
{
this.menuitem = bkmenuitem ;
}
public void setBookinfo(Bookmodel bookinfo) {
bookmarkURLTextField.setText(bookinfo.getUrl());
bookmarkTitleTextField.setText(bookinfo.getTitile());
this.bookinfo = bookinfo;
menuitem.setText(bookinfo.getTitile());
}