How to programmatically get text from TextField - javafx

I have this code to find all "id" names, but I want to use these names to now get the text from the same fxml.
#FXML
private void handleButtonAction(ActionEvent event) {
Node source = (Node) event.getSource();
Scene scene = source.getScene();
ObservableList<Node> stringArray = source.getParent().getChildrenUnmodifiable();
for (int index = 0; index < stringArray.size(); index++) {
if (stringArray.get(index).getId() != null) {
System.out.println(stringArray.get(index).getId());
}
}
}

Set fx:id to your TextField and call it from code.
In fxml it looks seems:
<TextField fx:id="yourTextField"/>
So you can declare a TextField variable in java-class using #FXML annotation
#FXML
TextField yourTextField;
yourTextField.getText();

Related

How to listen to on selected event in choice box javafx

Im using scenebuilder and I have come up with 3 choiceboxes. The second choicebox depends on the input of the first choicebox and the third depends on the 2nd. How can I achieve this?
I've tried this
#FXML
private ChoiceBox course;
course.getSelectionModel().selectedIndexProperty().addListener(
(ObservableValue<? extends Number> ov,
Number old_val, Number new_val) -> {
//some code here
}
);
But this event only occurs if i switch value, the first selection would not trigger this event, which is not what I want.
How can I achieve this, thanks in advance.
You can do something like this where everytime an action is done it will set the values of the next one. Make note of the .getItems().clear(); this will ensure the list is emptied everytime so that you don't have old values in the list. The for loop however is not important only there to add some variety to the text values I added
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
ChoiceBox<String> choiceBoxOne = new ChoiceBox<>();
choiceBoxOne.setPrefWidth(100);
choiceBoxOne.getItems().addAll("Choice1", "Choice2", "Choice3");
ChoiceBox<String> choiceBoxTwo = new ChoiceBox<>();
choiceBoxTwo.setPrefWidth(100);
ChoiceBox<String> choiceBoxThree = new ChoiceBox<>();
choiceBoxThree.setPrefWidth(100);
choiceBoxOne.setOnAction(event -> {
choiceBoxTwo.getItems().clear();
//The above line is important otherwise everytime there is an action it will just keep adding more
if(choiceBoxOne.getValue()!=null) {//This cannot be null but I added because idk what yours will look like
for (int i = 3; i < 6; i++) {
choiceBoxTwo.getItems().add(choiceBoxOne.getValue() + i);
}
}
});
choiceBoxTwo.setOnAction(event -> {
choiceBoxThree.getItems().clear();
//The above line is important otherwise everytime there is an action it will just keep adding more
if(choiceBoxTwo.getValue()!=null) {//This can be null if ChoiceBoxOne is changed
for (int i = 6; i < 9; i++) {
choiceBoxThree.getItems().add(choiceBoxTwo.getValue() + i);
}
}
});
VBox vBox = new VBox();
vBox.setPrefSize(300, 300);
vBox.setAlignment(Pos.TOP_CENTER);
vBox.getChildren().addAll(choiceBoxOne, choiceBoxTwo, choiceBoxThree);
primaryStage.setScene(new Scene(vBox));
primaryStage.show();
}
public static void main(String[] args) { launch(args); }
}

JavaFX set action to button in another class

I created listview in my application and its item has a delete button:
public Cell() {
super();
this.delete = new Button("delete");
// I have also image and other labels in this cell
this.hBox.getChildren().addAll(productImage, amountLabel, priceLabel, delete);
HBox.setHgrow(pane, Priority.ALWAYS);
delete.setOnAction(event -> getListView().getItems().remove(getItem()));
}
But in my main controller window when I click this button amount field and amountLabel must be changed which are my main controller class:
#FXML
void addToShopCart(ActionEvent event) {
selectedPart.setAmount(amount);
selectedPart.setSumma(amount*selectedPart.getPrice());
shopListView.getItems().add(selectedPart);
summa += amount*selectedPart.getPrice();
totalPriceLabel.setText(summa + "$");
} // this is when I add an item to the list
Now I don't know how to subtract amount from summa that was added. For this I tried return button like this:
Cell cell;
#FXML
void initialize() {
cell = new Cell();
shopListView.setCellFactory(param -> cell));
Button button = cell.getDeleteButton();
button.setOnAction(...//some action)
}
But it doesn't help. I tried to cut the code.

How to set the scrollPane to the desired vValue?

I have a tilepane inside a scrollpane. The tilepane is filled with buttons that have actions like delete or edit. After I delete or edit a button, the scrollpane automatically goes back to the top, which I don't want. I want it to remain at the current position (the position the user scrolled to).
I tried getting and setting the vValue of the scrollpane. getvValue gets the value and the setter sets it, but the scrollpane doesn't respond to it and goes back to the top after the action (delete/ edit). I tried a solution from this question: JavaFX ScrollPane setVvalue() not working as intended, but the layout() method doesn't do anything either. What am I doing wrong here? How do I make the scrollpane stay where it is?
EDIT: I found the problem, but still don't know how to fix it. Apparently setting and changing the visibility on the hBoxes in fxml puts the scrollpane back to the top. If I remove the setVisible methods and run it, I can delete items and the scrollpane stays in position. How to fix this?
On request I created a Minimal, Complete, and Verifiable example of my code. Run it, scroll down a bit, right click a button with a name and price on it and then click delete. It scrolls back up to the top.
This is my code:
public class Controller {
private static LinkedHashMap<String, BigDecimal> mProductMap = new LinkedHashMap<>();
#FXML private TilePane fieldContainer = new TilePane();
#FXML private ScrollPane scroll;
#FXML private Button deletebtn;
#FXML private Button editbtn;
#FXML private HBox homeBar;
#FXML private HBox actionBar;
#FXML
private void initialize() {
addProduct("Coffee", new BigDecimal("2.00"));
addProduct("Tea", new BigDecimal("2.00"));
addProduct("Cappuccino", new BigDecimal("2.00"));
addProduct("Espresso", new BigDecimal("2.00"));
addProduct("Cooky", new BigDecimal("2.00"));
addProduct("Candy", new BigDecimal("2.00"));
addProduct("Chocobar", new BigDecimal("2.00"));
addProduct("Cola", new BigDecimal("2.00"));
addProduct("Fanta", new BigDecimal("2.00"));
addProduct("Beer", new BigDecimal("2.00"));
addProduct("Salad", new BigDecimal("2.00"));
addProduct("Sandwich", new BigDecimal("2.00"));
addProduct("Water", new BigDecimal("2.00"));
addProduct("Cassis", new BigDecimal("2.00"));
}
// makes the delete and edit buttons appear after selecting a button from the tilepane
private void select(String selectedProduct) {
/*
the setVisible method for the hBoxes in fxml cause the scrollbar to go back to the top
without them, the scrollpane stays where it is.
I tried changing visibility with both setVisible and CSS, but they both cause the problem
I need the actionbar to appear when you select a button (right click on it)
*/
homeBar.setVisible(false);
actionBar.setVisible(true);
EventHandler<ActionEvent> delete = event -> {
deleteProduct(selectedProduct); // deletes an item from a LinkedHashMap
homeBar.setVisible(true);
actionBar.setVisible(false);
};
deletebtn.setOnAction(delete);
// I want the same to happen when the edit handler is used, scrollpane needs to remain its position
EventHandler<ActionEvent> edit = event -> {
editProduct(selectedProduct); // edits an item from a LinkedHashMap
homeBar.setVisible(true);
actionBar.setVisible(false);
};
editbtn.setOnAction(edit);
}
/*
Code below does not cause the problem, but I added it as a reference
*/
private void deleteProduct(String product) {
if (mProductMap.containsKey(product)) {
mProductMap.remove(product);
System.out.printf("%s has been deleted!%n", product);
} else {
System.out.printf("%s does not exist. Please try again.%n", product);
}
addButtons();
}
private void editProduct(String product) {
List<String> indexKeys = new ArrayList<>(mProductMap.keySet());
List<BigDecimal> indexValues = new ArrayList<>(mProductMap.values());
BigDecimal price = mProductMap.get(product); // gets the product's value (the price)
int indexKey = indexKeys.indexOf(product);
int indexValue = indexValues.indexOf(price);
if (mProductMap.containsKey(product)) {
int sizeBefore = mProductMap.size();
addingProduct();
int sizeAfter = mProductMap.size();
if (sizeAfter > sizeBefore) {
indexKeys.remove(product);
indexValues.remove(price);
mProductMap.remove(product);
// Make a new list to get the new entry at the end
List<Map.Entry<String,BigDecimal>> entryList = new ArrayList<>(mProductMap.entrySet());
Map.Entry<String, BigDecimal> lastEntry = entryList.get(entryList.size()-1);
String key = lastEntry.getKey();
BigDecimal value = lastEntry.getValue();
indexKeys.add(indexKey, key);
indexValues.add(indexValue, value);
mProductMap.clear();
// Put the keys and values from the two lists back to the map
for (int i=0; i<indexKeys.size(); i++) {
addProduct(indexKeys.get(i), indexValues.get(i));
}
}
} else {
System.out.printf("%s does not exist. Please try again.%n", product);
}
}
void addProduct(String product, BigDecimal price) {
mProductMap.put(product, price);
addButtons();
}
// Adding buttons to the TilePane fieldContainer in center of BorderPane
// One button per key-value pair of mProductMap
private void addButtons() {
// clears the TilePane to prevent duplicate buttons
fieldContainer.getChildren().clear();
for (Map.Entry<String, BigDecimal> entry : mProductMap.entrySet()) {
StackPane newField = new StackPane();
Button main = new Button();
main.setOnMousePressed(me -> {
if (me.getButton() == MouseButton.SECONDARY) { // = right click
select(entry.getKey());
}
});
main.setText(entry.getKey() + "\n" + entry.getValue());
newField.getChildren().add(main);
fieldContainer.setAlignment(Pos.TOP_LEFT);
fieldContainer.getChildren().add(newField);
}
}
// Popup for adding products to the Map with the + button
#FXML
private void addingProduct(){
Stage newStage = new Stage();
VBox popup = new VBox();
final BooleanProperty firstTime = new SimpleBooleanProperty(true); // Variable to store the focus on stage load
TextField product = new TextField("");
product.setId("product");
product.setPromptText("Enter the item name...");
// code to remove the focus from first textfield on stage load
product.focusedProperty().addListener((observable, oldValue, newValue) -> {
if(newValue && firstTime.get()){
popup.requestFocus(); // Delegate the focus to container
firstTime.setValue(false); // Variable value changed for future references
}
});
TextField price = new TextField("");
price.setId("price");
price.setPromptText("Enter the item price...");
Button submit = new Button("Submit");
Label label = new Label();
label.setId("label");
submit.setOnAction(e -> {
if ( (product.getText() != null && !product.getText().isEmpty() &&
price.getText() != null && !price.getText().isEmpty() ) ) {
addProduct(product.getText(), new BigDecimal(price.getText()) );
newStage.close();
} else {
label.setText("Fill in both fields");
}
});
popup.getChildren().add(product);
popup.getChildren().add(price);
popup.getChildren().add(submit);
popup.getChildren().add(label);
Scene stageScene = new Scene(popup, 300, 200);
newStage.setScene(stageScene);
newStage.showAndWait();
}
}
The FXML:
<BorderPane xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<top>
<StackPane>
<HBox fx:id="homeBar" styleClass="main-bar" visible="true">
<Button StackPane.alignment="BOTTOM_LEFT">Home</Button>
<Button onAction="#addingProduct" StackPane.alignment="BOTTOM_RIGHT">Add a new product</Button>
</HBox>
<HBox fx:id="actionBar" styleClass="main-bar" visible="false">
<Button fx:id="deletebtn" StackPane.alignment="BOTTOM_CENTER">Delete</Button>
<Button fx:id="editbtn" StackPane.alignment="BOTTOM_CENTER">Edit</Button>
<Button onAction="#addingProduct" StackPane.alignment="BOTTOM_RIGHT">Add a new product</Button>
</HBox>
</StackPane>
</top>
<center>
<ScrollPane fx:id="scroll" hbarPolicy="NEVER">
<TilePane fx:id="fieldContainer" prefColumns="2" prefTileHeight="100.0" prefTileWidth="144.0">
</TilePane>
</ScrollPane>
</center>
<bottom>
</bottom>
</BorderPane>
Main:
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I fixed it myself, with help from answers from this post: ScrollPane jumps to top when deleting nodes.
After deleting a button from the TilePane, the ScrollPane finds the next node to focus on, which by default is the first node from the pane. By requesting the focus on the TilePane (fieldContainer) the ScrollPane stays in place.
I added this code to both the delete and edit methods:
fieldContainer.requestFocus();

Adding multiple nodes to vbox javafx

I am new in JavaFx and I spend too much time trying to put radio button + textfield dynamically. After typing a number, I want to display my radio buttons and my TextFields in that way (blue and red ones)
But I got this:
I tried with vbox, hbox, both of them, but it did not work!
Can anyone figure out the problem in my code please!!! Thanks for your help
RadioButton[] btn = new RadioButton[100]; //our Collection to hold newly created Buttons
TextField[] xlist = new TextField[100]; //our Collection to hold newly created Buttons
TextField[] ylist = new TextField[100];
final ToggleGroup grpBtn = new ToggleGroup();
#FXML
private Group noeuds;
#FXML
private VBox vb2;
#FXML
private HBox hb2;
#FXML
public void addBtn(int i, RadioButton[] btn) {
btn[i] = new RadioButton();
btn[i].setText(String.valueOf(i + 1));
btn[i].setToggleGroup(grpBtn);
btn[i].setSelected(true);
btn[i].setTranslateX(-5);
btn[i].setTranslateY(-340);
btn[i].setPadding(new Insets(0, 0, 20, 20));
vb2.getChildren().add(btn[i]);
}
#FXML
public void addX(int i, TextField[] xlist) {
xlist[i] = new TextField();
xlist[i].setTranslateX(-80);
xlist[i].setTranslateY(40);
xlist[i].setStyle("-fx-background-color: red;");
xlist[i].setPrefSize(30, 30);
xlist[i].setTooltip(new Tooltip("X coordinate of " + (i + 1)));
hb2.getChildren().add(xlist[i]);
}
#FXML
public void addY(int i, TextField[] ylist) {
ylist[i] = new TextField();
ylist[i].setTranslateX(-78);
ylist[i].setTranslateY(40);
ylist[i].setStyle("-fx-background-color: blue;");
ylist[i].setPrefSize(30, 30);
ylist[i].setTooltip(new Tooltip("Y coordinate of" + (i + 1)));
hb2.getChildren().add(ylist[i]);
}
public void initialize(URL url, ResourceBundle rb) {
//some code
for (int i = 0; i < Integer.parseInt(nodeID.getText()); i++) {
addBtn(i, btn);
// System.out.println("jjjj"+btn.length);
addX(i, xlist);
// System.out.println("mmmm"+xlist.length);
addY(i, ylist);
}
}
This little app might help give you a boost. Read over the code and try to get an understanding. I tried to make comments in the code.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
*
* #author blj0011
*/
public class JavaFXApplication7 extends Application {
#Override
public void start(Stage primaryStage) {
AnchorPane root = new AnchorPane();
VBox vbox1 = new VBox();
vbox1.setSpacing(5);//Set vbox spacing
//Handles the number of row to be added to the vbox
for(int i = 0; i < 4; i++)
{
vbox1.getChildren().add(addNewRow(i));
}
root.getChildren().add(vbox1);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
//Method creates all the nodes for a new row.
HBox addNewRow(int rowNumber)
{
//Create nodes and adding correct spaceing
HBox hbox = new HBox();
hbox.setSpacing(5);
RadioButton radioButton = new RadioButton();
radioButton.setPrefHeight(25);
TextField textField = new TextField();
textField.setPrefWidth(40);
Label label = new Label(Integer.toString(rowNumber + 1));
label.setPrefHeight(25);
HBox trailingHBox = new HBox();
trailingHBox.setSpacing(5);
hbox.getChildren().addAll(radioButton, textField, label, trailingHBox);
//Event handler on textfield. Add right about of trailing textfields
textField.setOnKeyReleased((event)->{
if(textField.getText().trim().length() > 0 && Integer.parseInt(textField.getText()) > 0)//If textfield has some value greater than zero. I didn't catch for non integers
{
int tempInt = Integer.parseInt(textField.getText());
//clear trailingHBox so that new Trailing hbox can be added
if(trailingHBox.getChildren().size() > 0)
{
trailingHBox.getChildren().clear();
}
//add the correct number of textFields.
for(int i = 0; i < tempInt - 1; i++)
{
TextField tempTextField = new TextField();
tempTextField.setPrefWidth(20);
trailingHBox.getChildren().add(tempTextField);
}
//add the blue and red textfields
TextField textFieldBlue = new TextField();
textFieldBlue.setPrefWidth(40);
textFieldBlue.setStyle("-fx-background-color: BLUE");
TextField textFieldRed = new TextField();
textFieldRed.setPrefWidth(40);
textFieldRed.setStyle("-fx-background-color: RED");
trailingHBox.getChildren().addAll(textFieldBlue, textFieldRed);
}
else{
trailingHBox.getChildren().clear();//clear traingHbox if it's has no value
}
});
return hbox;
}
}

Javafx:Menuitem not taking value from controller

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

Resources