How to find index or information of clicked RadioButton - for-loop

I was wondering if there was anyway to either find the index when a certain RadioButton is pressed or to pass myBuns.get(i) when the RadioButton. Using the code below to create the RadioButtons
RadioButton rButton;
for (i = 0; i < myBuns.size(); i ++){
rButton = new RadioButton("" + myBuns.get(i));
rButton.setToggleGroup(bunGroup);
rButton.setOnAction(this);
this.getChildren().add(rButton);
}
Thanks for any help or suggestions!

You can get the index of the selected toggle using:
toggleGroup.getToggles().indexOf(toggleGroup.getSelectedToggle());
And the text of the selected toggle using:
((RadioButton) toggleGroup.getSelectedToggle()).getText();
By placing the code in the change listener for the selected toggle property, you can monitor when the selected toggle changes and take action as appropriate.
Sample App
import javafx.application.Application;
import javafx.collections.*;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import java.util.stream.*;
public class ToggleIndexer extends Application {
#Override
public void start(final Stage stage) throws Exception {
ToggleGroup toggleGroup = new ToggleGroup();
ObservableList<RadioButton> buttons = IntStream.range(0, 5)
.mapToObj(i -> new RadioButton("Radio " + i))
.collect(Collectors.toCollection(FXCollections::observableArrayList));
toggleGroup.getToggles().setAll(buttons);
Label selectedIndex = new Label();
selectedIndex.setFont(Font.font("monospace"));
Label selectedItem = new Label();
selectedItem.setFont(Font.font("monospace"));
toggleGroup.selectedToggleProperty().addListener((observable, oldValue, newValue) -> {
if (newValue == null) {
selectedIndex.setText("");
selectedItem.setText("");
} else {
final int selectedIndexValue =
toggleGroup.getToggles().indexOf(newValue);
selectedIndex.setText("Selected Index: " + selectedIndexValue);
final String selectedItemText =
((RadioButton) toggleGroup.getSelectedToggle()).getText();
selectedItem.setText( "Selected Item: " + selectedItemText);
}
});
VBox layout = new VBox(8);
layout.setPadding(new Insets(10));
layout.setPrefWidth(250);
layout.getChildren().setAll(buttons);
layout.getChildren().addAll(selectedItem, selectedIndex);
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) throws Exception {
launch(args);
}
}

Related

JAVA FX CLASS GUI

The program below makes use of the java fx class to create a graphical user interface to validate if a person is eligible to drink. The problem is that the output is displayed on the console not on the graphical user interface I. How do I fix this problem ?
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ValidateAge extends Application {
//Class Variables
Stage window;
Scene scene;
Button button;
//Main Methods
public static void main(String[] args) { // Main
launch(args);
}
#Override //Method that creates Graphical User Interface
public void start(Stage primaryStage) throws Exception {
window = primaryStage;
window.setTitle("Validate Age For Drinking");// displays "Validate age" on top of window
TextField ageInput = new TextField();// Object for display text field
Label label1 = new Label();
button = new Button("Verify Age"); //Displays Verify Age Buttom
button.setOnAction( e -> isInt(ageInput, ageInput.getText() , label1));
//Parameters for Layouts
VBox layout = new VBox(10);
layout.setPadding(new Insets(20, 20, 20, 20)); //sets the size of the layout
layout.getChildren().addAll(ageInput, label1, button);
scene = new Scene(layout, 400, 550);//sets dimensions for scene
window.setScene(scene);
window.show();
}
//Validates user age
private int isInt(TextField input, String message, Label label){
// validates to see if user is above 18 to drink
try{
int age = Integer.parseInt(input.getText());
if(age< 18) {
label.setText("You are not allowed to drink");
}else {
System.out.println("You are allowed to drink");
}
}catch(NumberFormatException e){ // displays when user fails to type in a number
System.out.println("Error: " + message + " Tye in a number ");
}
return 0;
}
}
Instead of
System.out.println("You are allowed to drink");
put
label.setText("You are allowed to drink");
And you are good to go.

Get row from selected cell in TableView in JavaFX when setCellSelectionEnabled(true)

I have the following code which works great when I have standard row selection (always single, never multi).
//This is needed to set the X & Y coordinates of the stage for edit.
myTable.setRowFactory(tableView -> {
TableRow<MyDTO> row = new TableRow<MyDTO>();
row.selectedProperty().addListener((obs, wasSelected, isNowSelected) -> {
if (isNowSelected) {
lastSelectedRow.set(row);
}
});
return row ;
});
I am using the row to get the bounds in parent so that when a user selects to edit that row, I can pop a modal window up under the row for them to edit this.
However, my table is also editable for the common fields where there is no look up needed, etc. In that case I want to edit in the table. All this is working, however to make it more user friendly, I want to have cell selection turned on, but when I do that, the row.selectedProptery() listener doesn't fire.
How can I accomplish that, without trying to listen to the selectedProperty() of each cell?
Thanks
I don't think there's a way to do this without registering a listener with the selection property of each cell, via a cell factory on each table column.
However, this isn't too difficult, and can be done both generically (i.e. with the same code no matter the type of the table column) and also respecting any other cell factory behavior you need. Here is a SSCCE:
import java.util.Random;
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.binding.DoubleBinding;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Callback;
public class SelectedTableCellTracking extends Application {
private final ObjectProperty<TableCell<?,?>> selectedCell = new SimpleObjectProperty<>();
#Override
public void start(Stage primaryStage) {
TableView<Item> table = new TableView<>();
TableColumn<Item, String> itemCol = column("Item", Item::nameProperty);
TableColumn<Item, Number> valueCol = column("Value", Item::valueProperty);
table.getColumns().add(itemCol);
table.getColumns().add(valueCol);
Random rng = new Random();
for (int i = 1 ; i <= 100; i++) {
table.getItems().add(new Item("Item "+i, rng.nextInt(1000)));
}
table.getSelectionModel().setCellSelectionEnabled(true);
Rectangle highlight = new Rectangle();
highlight.setManaged(false);
highlight.setHeight(12);
highlight.setFill(Color.CORAL);
StackPane root = new StackPane(table, highlight);
selectedCell.addListener((obs, oldCell, newCell) -> {
if (newCell == null) {
highlight.setVisible(false);
} else {
highlight.setVisible(true);
highlight.setX(newCell.localToScene(newCell.getBoundsInLocal()).getMinX());
highlight.setWidth(newCell.getWidth());
highlight.setY(newCell.localToScene(newCell.getBoundsInLocal()).getMaxY());
}
});
table.getColumns().forEach(this::addCellSelectionListenerToColumn);
Scene scene = new Scene(root, 800, 800);
primaryStage.setScene(scene);
primaryStage.show();
}
private <S,T> void addCellSelectionListenerToColumn(TableColumn<S,T> col) {
Callback<TableColumn<S,T>, TableCell<S,T>> currentCellFactory = col.getCellFactory();
col.setCellFactory(tc -> {
TableCell<S,T> cell = currentCellFactory.call(tc);
cell.selectedProperty().addListener((obs, wasSelected, isNowSelected) -> {
if (isNowSelected) {
selectedCell.set(cell);
}
});
return cell ;
});
}
private static <S,T> TableColumn<S,T> column(String title, Function<S, ObservableValue<T>> property) {
TableColumn<S,T> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
return col ;
}
public static class Item {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty value = new SimpleIntegerProperty();
public Item(String name, int value) {
setName(name);
setValue(value);
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final IntegerProperty valueProperty() {
return this.value;
}
public final int getValue() {
return this.valueProperty().get();
}
public final void setValue(final int value) {
this.valueProperty().set(value);
}
}
public static void main(String[] args) {
launch(args);
}
}

JavaFx, how to add menuBar and drawingPane

I'an busy with some demo, drawing some lines in a scroll window. So far so good, but now it's possible to draw lines on the menuBar, which should not be possible of course. See code below. Please help!
This is what happens:
See output here
The wrong code:
package Example12a;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class Example12a extends Application {
public static void main(String[] args) {
launch(args);
}
private Line curLine;
#Override
public void start(Stage stage) throws Exception {
Pane drawingPane = new Pane();
BorderPane theBorderPane = new BorderPane();
drawingPane.setPrefSize(800, 800);
drawingPane.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
MenuBar menuBar = new MenuBar();
// --- Menu File
Menu menuFile = new Menu("File");
MenuItem add = new MenuItem("Save");
add.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
System.out.println("Save");
}
});
menuFile.getItems().addAll(add);
//yOffset = (int)menuBar.getHeight();
Menu menuEdit = new Menu("Edit");
Menu menuView = new Menu("View");
menuBar.getMenus().addAll(menuFile, menuEdit, menuView);
theBorderPane.setTop(menuBar);
ScrollPane scrollPane = new ScrollPane(theBorderPane);
scrollPane.setPrefSize(300, 300);
scrollPane.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
scrollPane.setFitToWidth(true);
scrollPane.setFitToHeight(true);
scrollPane.setStyle("-fx-focus-color: transparent;");
theBorderPane.setOnMousePressed(event -> {
if (!event.isPrimaryButtonDown()) {
return;
}
curLine = new Line(
event.getX(), event.getY(),
event.getX(), event.getY()
);
theBorderPane.getChildren().add(curLine);
});
theBorderPane.setOnMouseDragged(event -> {
if (!event.isPrimaryButtonDown()) {
return;
}
if (curLine == null) {
return;
}
curLine.setEndX(event.getX());
curLine.setEndY(event.getY());
double mx = Math.max(curLine.getStartX(), curLine.getEndX());
double my = Math.max(curLine.getStartY(), curLine.getEndY());
if (mx > theBorderPane.getMinWidth()) {
theBorderPane.setMinWidth(mx);
}
if (my > theBorderPane.getMinHeight()) {
theBorderPane.setMinHeight(my);
}
});
theBorderPane.setOnMouseReleased(event -> curLine = null);
theBorderPane.setCenter(drawingPane);
Scene scene = new Scene(scrollPane);
stage.setMinWidth(100);
stage.setMinHeight(100);
stage.setScene(scene);
stage.show();
}
}
Fixed your layout.
What i did was:
The BorderPane is now your root Pane.
The ScrollPane is the center of the BorderPane and its content is the drawingPane.
The MenuBar is still the the Top of the BorderPane.
I also changed the Mouse Events from borderPane to drawingPane and the lines are added to the drawingPane instead of the borderPane.
So its working fine.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class Example12a extends Application {
public static void main(String[] args) {
launch(args);
}
private Line curLine;
#Override
public void start(Stage stage) throws Exception {
Pane drawingPane = new Pane();
BorderPane theBorderPane = new BorderPane();
drawingPane.setPrefSize(800, 800);
drawingPane.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
MenuBar menuBar = new MenuBar();
// --- Menu File
Menu menuFile = new Menu("File");
MenuItem add = new MenuItem("Save");
add.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
System.out.println("Save");
}
});
menuFile.getItems().addAll(add);
//yOffset = (int)menuBar.getHeight();
Menu menuEdit = new Menu("Edit");
Menu menuView = new Menu("View");
menuBar.getMenus().addAll(menuFile, menuEdit, menuView);
theBorderPane.setTop(menuBar);
ScrollPane scrollPane = new ScrollPane(drawingPane);
scrollPane.setPrefSize(300, 300);
scrollPane.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
scrollPane.setFitToWidth(true);
scrollPane.setFitToHeight(true);
scrollPane.setStyle("-fx-focus-color: transparent;");
drawingPane.setOnMousePressed(event -> {
if (!event.isPrimaryButtonDown()) {
return;
}
curLine = new Line(
event.getX(), event.getY(),
event.getX(), event.getY()
);
drawingPane.getChildren().add(curLine);
});
drawingPane.setOnMouseDragged(event -> {
if (!event.isPrimaryButtonDown()) {
return;
}
if (curLine == null) {
return;
}
curLine.setEndX(event.getX());
curLine.setEndY(event.getY());
double mx = Math.max(curLine.getStartX(), curLine.getEndX());
double my = Math.max(curLine.getStartY(), curLine.getEndY());
if (mx > drawingPane.getMinWidth()) {
drawingPane.setMinWidth(mx);
}
if (my > drawingPane.getMinHeight()) {
drawingPane.setMinHeight(my);
}
});
theBorderPane.setOnMouseReleased(event -> curLine = null);
theBorderPane.setCenter(scrollPane);
Scene scene = new Scene(theBorderPane);
stage.setMinWidth(100);
stage.setMinHeight(100);
stage.setScene(scene);
stage.show();
}
}
Note:
if your trying to make a Drawing Programm I would prevere to Render all Lines in a Canvas instead of using the Line class. The Canvas is much faster with many Lines.

Text area for progress bar

I would like to add a text area where the user can see some information that i can see in the console while the progress bar is updating.
How can i add the text area ?
Here is a sample of the code I have used to make the progress bar. Can i add below the progress bar the text area which should fill while computations are mare?
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class ProgressDialogExample extends Application {
static int option = 0;
static ProgressForm pForm = new ProgressForm();
#Override
public void start(Stage primaryStage) {
Button startButton = new Button("Start");
startButton.setOnAction(e -> {
// In real life this task would do something useful and return
// some meaningful result:
Task<Void> task = new Task<Void>() {
#Override
public Void call() throws InterruptedException {
for (int i = 0; i < 10; i++) {
updateProgress(i, 10);
Thread.sleep(200);
}
updateProgress(10, 10);
return null;
}
};
// binds progress of progress bars to progress of task:
pForm.activateProgressBar(task);
// in real life this method would get the result of the task
// and update the UI based on its value:
task.setOnSucceeded(event -> {
startButton.setDisable(false);
});
startButton.setDisable(true);
pForm.getDialogStage().show();
Thread thread = new Thread(task);
thread.start();
});
StackPane root = new StackPane(startButton);
Scene scene = new Scene(root, 350, 75);
primaryStage.setScene(scene);
primaryStage.show();
}
private int closeWindow() {
return option;
}
private static void setCloseWindow() {
// TODO Auto-generated method stub
option = 1;
}
public static class ProgressForm {
private final Stage dialogStage;
private final ProgressBar pb = new ProgressBar();
private final ProgressIndicator pin = new ProgressIndicator();
public ProgressForm() {
dialogStage = new Stage();
dialogStage.initStyle(StageStyle.UTILITY);
// dialogStage.setResizable(false);
// dialogStage.setWidth(400);
// dialogStage.setHeight(300);
// final VBox vbox = new VBox();
dialogStage.initModality(Modality.APPLICATION_MODAL);
final Button exitButton = new Button("Exit");
exitButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
pForm.getDialogStage().close();
setCloseWindow();
}
});
// PROGRESS BAR
pb.setProgress(-1F);
pin.setProgress(-1F);
final HBox hb = new HBox();
hb.setSpacing(5);
hb.setAlignment(Pos.CENTER);
hb.getChildren().addAll(pb, pin, exitButton);
Scene scene = new Scene(hb);
dialogStage.setScene(scene);
}
public void activateProgressBar(final Task<?> task) {
pb.progressProperty().bind(task.progressProperty());
pin.progressProperty().bind(task.progressProperty());
dialogStage.show();
}
public Stage getDialogStage() {
return dialogStage;
}
}
public static void main(String[] args) {
launch(args);
}
}
Have you heard of Label Labelled before use Label instead of the Text Node you want to use and write your text when you want to, when you want to show your Progressbars do
Label.setGraphic(myprogressbarNode);
Hope it helps
EDIT
I would like to add a text area where the user can see some information that i can see in the console while the progress bar is updating... Can i add below the progress bar the text area which should fill while computations are mare?
and i gave you a solution to it.
suppose you have your ProgressBar pb; and you are adding your ProgressBar to a StackPane you do not have to add the ProgressBar directly but rather add your Text which you will implement that by Label so presume your Label is lb this is how your code will look like
StackPane sp; // parent
ProgressBar pb; // progress indicator
Lable lb; // my text area
sp.getChildren().add(lb);// i have added the text area
lb.setGraphic(pb); we have added the progressbar to the text area
lb.setContentDisplay(ContentDisplay.***);//the *** represents the position you want your graphic
//whether top or left or bottom
//now you are done, your pb will show aligned to your lb, and be updated
//if you want to show text lb.setText("your text");
how implicit is this? :-)
Try adding a listener to the task's messageProperty that will append the text to a TextArea whenever it is changed.
TextArea ta = new TextArea();
public void activateTextArea(final Task<?> task) {
task.messageProperty().addListener((property, oldValue, newValue) -> {
ta.setText(ta.getText() + "\n" + newValue);
});
}
Then put something like this inside the task:
Task<Void> task = new Task<Void>() {
#Override
public Void call() throws InterruptedException {
for (int i = 0; i < 10; i++) {
updateProgress(i, 10);
updateMessage((i*10) + "% done");
Thread.sleep(200);
}
updateProgress(10, 10);
updateMessage("All done!");
return null;
}
};

Add EventHandler to ImageView contained in TilePane contained in VBox?

I have the following schema:
A VBox, containing a HBox and a TilePane.
In HBox are buttons, labels, and text fields.
Every time I click on the root (HBox), I should add a ImageView to the tile pane. This ImageView shold contain an image (example: "2.jpg"). Maximum of tile pane components is 5.
Every time I click the image, i should load a new image to the clicked ImageView, exemple "1.jpg". It is not working. When I click on my image it is like i'm clicking on the root so it creates another cell of TilePane. Here's the code, can you help me?
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package dadao1;
import java.util.HashSet;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.TilePane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
/**
*
* #author Ambra
*/
public class Dadao1 extends Application {
VBox root;
HashSet dadi = new HashSet();
//static int numeroDadi = 0;
#Override
public void start(Stage primaryStage) {
setGui();
Scene scene = new Scene(root, 300, 300);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
*This private method sets up the GUI.
* No parameters are required
*/
private void setGui(){
root = new VBox();
HBox buttons = new HBox();
final Button newGame = new Button("New Game");
final Button print = new Button("Print");
final Button animation = new Button("Moving");
animation.addEventHandler(ActionEvent.ACTION, new EventHandler<ActionEvent>() {
// this button is labeled "Moving" at the begin. If pressed it changes its label to "Dissolving" and viceversa.
#Override
public void handle(ActionEvent event) {
if (animation.getText().equals(new String("Moving")))
animation.setText("Dissolving");
else animation.setText("Mooving");
}
});
final Label score = new Label("Total");
final TextField points = new TextField();
final Label pointsLabel = new Label("Score");
root.setStyle("-fx-background-color: green");
buttons.getChildren().addAll(newGame,print,animation,score,points,pointsLabel);
final TilePane dadiPane = new TilePane();
dadiPane.setVgap(10);
dadiPane.setHgap(10);
root.getChildren().addAll(buttons, dadiPane);
root.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if(dadi.size()<5){
System.out.println("Adding img");
final ImageView img = new ImageView("2.jpg");
// should I put final in front of ImageView?
img.addEventHandler(ActionEvent.ACTION, new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
// I want that when a tile is pressed an event occours.
// that event should be "add a new image to the ImageView just clicked",
// for example: img is not "2.jpg" but "3.jpj", by the way, I'm not able neither
// to to print the folowing messagge :(
// It's like my root is pressed even if my mouse ha clicked at the image in img var.
System.out.println("Tile pressed ");
}
});
dadi.add(img);
dadiPane.getChildren().add(img);
}else System.out.println("You cannot create more than 5 dices");
}
});
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
ImageViews don't generate ActionEvents; so it is no surprise that your event handler is never invoked. Since the mouse event is not processed by the ImageView, it propagates up to the container.
Try
img.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println("Tile pressed ");
event.consume();
}
});
#James_D is correct; but note for Java 8 you can use the simpler syntax:
img.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
System.out.println("Tile pressed ");
event.consume();
});
Note that MouseEvent.MOUSE_CLICKED is a class from javafx, not from java.awt.event package
imgView. addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, event -> {
//event clicked here
});
For someone who mistakenly import java.awt.event.MouseEvent class

Resources