javafx adding button to grid pane - java

I am adding button to grid pane dynamically but after giving them function they all show same function and i don't knows why?
import java.awt.Panel;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
public class TestController implements Initializable {
#FXML
Panel mpanel;
#FXML
GridPane gpnael;
int x=0,y=0,i=0,y1=0;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
#FXML
private void add(ActionEvent event) {
y1++;
Button temp = new Button("Button " + i);
temp.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
System.out.println("button"+y1);
}
});
gpnael.add(temp,i++,1);
}
}
now i have added three button to grid pane when i click on each button they show same output.
I want that they all show different output as assigned .

You are not defining it in the buttons, you are always using a non final int to express your values you should try do make them with unique values or to set an id for each button and get the value from the id:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class ButtonsOnGPanel extends Application {
private int i = 0;
private GridPane gpnael = new GridPane();
#Override
public void start(Stage stage) throws Exception {
Pane root = new Pane();
while(i<3){
addButton();
}
root.getChildren().add(gpnael);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
private void addButton() {
i++;
final Button temp = new Button("Button " + i);
final int numButton= i;
temp.setId("" + i);
temp.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
System.out.println("id(" + temp.getId() + ") = " + numButton);
}
});
gpnael.add(temp, i, 1);
}
public static void main(String[] args) {
launch(args);
}
}
And if you want to use lambda expressions:
temp.setOnAction((ActionEvent e) -> {
System.out.println("id(" + temp.getId() + ") = " + numButton);
});

Related

Listen to changes in array

I need some help if you can spare a few minutes.
I am in a bit of a pickle as I try to make this work.
I have a javaFX class like this
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class FoorballTeam extends Application {
int i1=0;
int i3=0;
String[] PlayerNames = new String[12];
int[] goals = new int[12];
#Override
public void start(Stage primaryStage) {
player[] playerData = new player[12];
Button btn = new Button();
btn.setText("add Player");
GridPane root = new GridPane();
root.add(btn,0,0);
int i2;
for (i2=0;i2<=11;i2++)
{playerData[i2]=new player();}
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
playerData[i3].player(root, i3);
i3++;
}
});
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public String[] getPlayerNames() {
return PlayerNames;
}
public void setPlayerNames(String[] PlayerNames) {
this.PlayerNames = PlayerNames;
}
public int[] getGoals() {
return goals;
}
public void setGoals(int[] goals) {
this.goals = goals;
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
and a second class named player like this
import javafx.event.EventType;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
public class player {
String NameOfPlayer = new String();
int goalsOfPlayer;
public void player (GridPane root,int numberOfPlayer)
{
TextField name = new TextField();
TextField goals = new TextField();
GridPane grid = new GridPane();
grid.add(name,0,0);
grid.add(goals,1,0);
root.add(grid,0,numberOfPlayer+1);
System.out.println("player " + numberOfPlayer + " added");
name.textProperty().addListener((observable, oldValue, newValue) -> {
NameOfPlayer=newValue;
});
goals.textProperty().addListener((observable, oldValue, newValue) -> {
goalsOfPlayer=Integer.parseInt(newValue);
});
}
}
I want every time that I make a change to a players name or goals to pass this change on the two arrays PlayerNames[] and goals[] of the main class.
for example if player1 changes goals from 1 to 2 I want the goals[1]=2.
Also is it possible to put a listener to this two arrays so when a player changes name or goals to trigger the listener.
Any help will be appreciated.
One simple solution is to warp the int[] array with an observable list, and listen to changes in this list :
import java.util.Arrays;
import java.util.Random;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class ListenToArrayCahnges extends Application {
private final int SIZE = 12;
private final Integer[] goals = new Integer[SIZE];
private final Random rand = new Random();
private int counter = 0;
#Override
public void start(Stage primaryStage) {
Arrays.fill(goals, 0); //initial values
//Warp array with an observable list. list back by array so it is of fixed length
ObservableList<Integer> goalsList = FXCollections.observableArrayList(Arrays.asList(goals));
//add listener to list
goalsList.addListener((ListChangeListener<Integer>) c ->{
//respond to list changes
System.out.println("Goals changed to : "+ goalsList);
});
//button to change the list
Button btn = new Button();
btn.setText("Add goal");
btn.setOnAction(event -> {
goalsList.set(counter, rand.nextInt(100));
counter = ++counter % SIZE ; //increment counter 0,1,2....11 and back to 0
});
GridPane root = new GridPane();
root.add(btn,0,0);
Scene scene = new Scene(root, 150, 50);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Note that the posted mcve represents the problem that needs to be solved (or in this case a solution to it), and not the specific application or use case.

How to use jfxtra Magnifier and draw Rectangle on ImageView at the same time?

I'm trying to use the Magnifier from jfxtras-labs 2.2 to see more details on an image. At the same time, I want to draw a rectangle on top of this image. The problem is, that the Magnifier blocks all other events.
Here is my sample code:
package magnifiertest;
import java.io.File;
import javax.imageio.ImageIO;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import jfxtras.labs.scene.control.Magnifier;
public class TestMagnifier extends Application {
Group groupForRectangles;
ImageView pageImageView;
private boolean new_rectangle_is_being_drawn;
private Rectangle new_rectangle;
private double starting_point_x;
private double starting_point_y;
public static void main(String[] args) {
launch();
}
#Override
public void start(Stage primaryStage) throws Exception {
StackPane root = new StackPane();
groupForRectangles = new Group();
groupForRectangles = new Group();
pageImageView = new ImageView();
pageImageView.setPreserveRatio(true);
pageImageView.setFitHeight(800);
pageImageView.setFitWidth(600);
pageImageView.setImage(SwingFXUtils.toFXImage(ImageIO.read(new File("/sample/Penguins.jpg")), null));
groupForRectangles.setOnMouseDragged(event -> {
setOnMouseDragged(event);
});
groupForRectangles.setOnMousePressed(event -> {
setOnMousePressed(event);
});
groupForRectangles.setOnMouseReleased(event -> {
setOnMouseReleased(event);
});
//If you outcomment the following lines, the rectangle drawing works
Magnifier m = new Magnifier(pageImageView);
groupForRectangles.getChildren().add(pageImageView);
groupForRectangles.getChildren().add(m);
root.getChildren().add(groupForRectangles);
primaryStage.setScene(new Scene(root, 800, 600));
primaryStage.show();
}
public void setOnMousePressed(MouseEvent event) {
System.out.println("mouse pressed");
if (new_rectangle_is_being_drawn == false) {
starting_point_x = event.getX();
starting_point_y = event.getY();
System.out.println(starting_point_x + " ; " + starting_point_y);
groupForRectangles.getChildren().remove(new_rectangle);
new_rectangle = new Rectangle();
new_rectangle.setFill(Color.TRANSPARENT);
new_rectangle.setStroke(Color.BLACK);
groupForRectangles.getChildren().add(new_rectangle);
new_rectangle_is_being_drawn = true;
}
}
public void setOnMouseDragged(MouseEvent event) {
if (new_rectangle_is_being_drawn == true) {
double current_ending_point_x = event.getX();// - sub.getLayoutX();
double current_ending_point_y = event.getY();// - sub.getLayoutY();
adjust_rectangle_properties(starting_point_x, starting_point_y, current_ending_point_x,
current_ending_point_y, new_rectangle);
}
}
public void setOnMouseReleased(MouseEvent event) {
if (new_rectangle_is_being_drawn == true) {
new_rectangle.setFill(Color.TRANSPARENT);
new_rectangle_is_being_drawn = false;
}
}
void adjust_rectangle_properties(double starting_point_x, double starting_point_y, double ending_point_x,
double ending_point_y, Rectangle given_rectangle) {
given_rectangle.setX(starting_point_x);
given_rectangle.setY(starting_point_y);
given_rectangle.setWidth((ending_point_x - starting_point_x));
given_rectangle.setHeight((ending_point_y - starting_point_y));
if (given_rectangle.getWidth() < 0) {
given_rectangle.setWidth(-given_rectangle.getWidth());
given_rectangle.setX(given_rectangle.getX() - given_rectangle.getWidth());
}
if (given_rectangle.getHeight() < 0) {
given_rectangle.setHeight(-given_rectangle.getHeight());
given_rectangle.setY(given_rectangle.getY() -
given_rectangle.getHeight());
}
}
}
Thanks.

JavaFX Change text under Progress Indicator

I want to change the text under Progress Indicator. By default, when the ProgressIndicator has completed its Progress the text is Done, I want to be able to edit this text with any user-defined text or text depending on the locale.
When I run the program output shows that text has been changed, but on the GUI it doesn't change. Please look at the following pictures :
MCVE
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Main extends Application {
Task copyWorker;
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Background Processes");
Group root = new Group();
Scene scene = new Scene(root, 330, 120, Color.WHITE);
BorderPane mainPane = new BorderPane();
root.getChildren().add(mainPane);
final Label label = new Label("Files Transfer:");
final ProgressIndicator progressIndicator = new ProgressIndicator(0);
progressIndicator.progressProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> ov, Number t, Number newValue) {
progressIndicator .applyCss();
// If progress is 100% then show Text
if (newValue.doubleValue() >= 1.0) {
// Apply CSS so you can lookup the text
Text text = (Text) progressIndicator .lookup(".percentage");//also I checked .lookup(.text.percentage) version
System.out.println(text.getText());
// This text replaces "Done"
text.setText("some text");
//for testing
Text x= (Text) progressIndicator .lookup(".percentage");
System.out.println(x.getText());//output shows that the text under progress indicator is changed
}
}});
final HBox hb = new HBox();
hb.setSpacing(5);
hb.setAlignment(Pos.CENTER);
hb.getChildren().addAll(label, progressIndicator);
mainPane.setTop(hb);
final Button startButton = new Button("Start");
final Button cancelButton = new Button("Cancel");
final HBox hb2 = new HBox();
hb2.setSpacing(5);
hb2.setAlignment(Pos.CENTER);
hb2.getChildren().addAll(startButton, cancelButton);
mainPane.setBottom(hb2);
startButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
startButton.setDisable(true);
progressIndicator.setProgress(0);
cancelButton.setDisable(false);
copyWorker = createWorker();
progressIndicator.progressProperty().unbind();
progressIndicator.progressProperty().bind(copyWorker.progressProperty());
copyWorker.messageProperty().addListener(new ChangeListener<String>() {
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
System.out.println(newValue);
}
});
new Thread(copyWorker).start();
}
});
cancelButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
startButton.setDisable(false);
cancelButton.setDisable(true);
copyWorker.cancel(true);
progressIndicator.progressProperty().unbind();
progressIndicator.setProgress(0);
System.out.println("cancelled.");
}
});
primaryStage.setScene(scene);
primaryStage.show();
}
public Task createWorker() {
return new Task() {
#Override
protected Object call() throws Exception {
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
updateMessage("100 milliseconds");
updateProgress(i + 1, 10);
}
return true;
}
};
}
}
You need to change the text of the ProgressIndicator as well as set the width of the ProgressIndicator to the new width of the Text.
progressIndicator.progressProperty().addListener((ov, oldValue, newValue) -> {
Text text = (Text) progressIndicator.lookup(".percentage");
if(text!=null && text.getText().equals("Done")){
text.setText("New Text");
progressIndicator.setPrefWidth(text.getLayoutBounds().getWidth());
}
});
Complete Code
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Main extends Application {
Task copyWorker;
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Background Processes");
Group root = new Group();
Scene scene = new Scene(root, 330, 120, Color.WHITE);
BorderPane mainPane = new BorderPane();
root.getChildren().add(mainPane);
final Label label = new Label("Files Transfer:");
final ProgressIndicator progressIndicator = new ProgressIndicator(0);
final HBox hb = new HBox();
hb.setSpacing(5);
hb.setAlignment(Pos.CENTER);
hb.getChildren().addAll(label, progressIndicator);
mainPane.setTop(hb);
final Button startButton = new Button("Start");
final Button cancelButton = new Button("Cancel");
final HBox hb2 = new HBox();
hb2.setSpacing(5);
hb2.setAlignment(Pos.CENTER);
hb2.getChildren().addAll(startButton, cancelButton);
mainPane.setBottom(hb2);
startButton.setOnAction(event -> {
startButton.setDisable(true);
progressIndicator.setProgress(0);
cancelButton.setDisable(false);
copyWorker = createWorker();
progressIndicator.progressProperty().unbind();
progressIndicator.progressProperty().bind(copyWorker.progressProperty());
new Thread(copyWorker).start();
});
cancelButton.setOnAction(event -> {
startButton.setDisable(false);
cancelButton.setDisable(true);
copyWorker.cancel(true);
progressIndicator.progressProperty().unbind();
progressIndicator.setProgress(0);
});
primaryStage.setScene(scene);
primaryStage.show();
progressIndicator.progressProperty().addListener((observable, oldValue, newValue) -> {
Text text = (Text) progressIndicator.lookup(".percentage");
if (text != null && text.getText().equals("Done")) {
text.setText("New Text");
progressIndicator.setPrefWidth(text.getLayoutBounds().getWidth());
}
});
}
public Task createWorker() {
return new Task() {
#Override
protected Object call() throws Exception {
for (int i = 0; i < 10; i++) {
Thread.sleep(500);
updateMessage("2000 milliseconds");
updateProgress(i + 1, 10);
}
return true;
}
};
}
public static void main(String[] args) {
Application.launch(args);
}
}
It's posiible to change ProgressIndicator label (and all other default labels, like TextField context menu labels) by overwrite controls bundle file. In this file you have field:
ProgressIndicator.doneString=YourTextHere
How to overwrite ResourceBundle file you'll find here:
https://stackoverflow.com/a/48773353/7746751

How to wait for some action to be completed using progress indicator in javafx?

I am having one code that send command to server.
public static void createAndSendCommand(String action, byte[] data) {
if (action.equals(OE_Constants.ACTION_UPDATE)) {
File file = new File(OE_Constants.FILE_BACKUP_TOPOLOGY);
Command command = ConnectionManager.populateData(file);
FrontEndClient.sendCommandToServer(command);
}
}
and
public static boolean sendCommandToServer(Command command) {
try {
outStream.writeObject(command);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
And I am receiving result like below.
public void receiveResultFromServer() {
try {
while(!clientSocket.isClosed()) {
CommandExecResult result;
try {
result = (CommandExecResult) inStream.readObject();
ConnectionManager.parseCommandExecutionResult(result);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
Now I want to wait for command to be successfully executed on server till the result of it is received by client. I want to show some Progress indicator type of UI ....how to do that?
Thanks!
Use a Task or a Service for your long running server calls.
Use Task.updateProgress() to inform on the current progress / work done.
Bind the progressProperty of your running Task to a ProgressBar or ProgressIndicator.
You specified the tags java and javafx. Here is my solution for javafx. It is a simple dialog that can be updated from 'outside' via binding.
WorkingDialog.java:
package stackoverflow.progress;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Logger;
import javafx.application.Platform;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.WindowEvent;
public final class WorkingDialog extends Stage implements Initializable {
private static final Logger LOG = Logger.getLogger(WorkingDialog.class.getName());
public SimpleDoubleProperty progress = new SimpleDoubleProperty(0);
public WorkingDialog(String title, Stage owner) {
super();
setTitle(title);
initStyle(StageStyle.UTILITY);
initModality(Modality.APPLICATION_MODAL);
initOwner(owner);
double w = 300;
double h = 200;
setWidth(w);
setHeight(h);
double dx = (owner.getWidth() - w) / 2;
double dy = (owner.getHeight() - h) / 2;
setX(owner.xProperty().get() + dx);
setY(owner.yProperty().get() + dy);
setResizable(false);
showDialog(progress);
}
public void hideDialog() {
Platform.runLater(() -> {
hide();
});
}
public void setTitleText(String title) {
Platform.runLater(() -> {
setTitle(title);
});
}
private void showDialog(SimpleDoubleProperty progress) {
//scene : gridPane : 0,0->progressbar,0,1->borderpane : center->button
GridPane gridPane = new GridPane();
gridPane.setGridLinesVisible(false);
gridPane.setPadding(new Insets(10));
gridPane.setHgap(5);
gridPane.setVgap(5);
setOnCloseRequest((WindowEvent e) -> {
e.consume();
});
ProgressBar pb = new ProgressBar(-1);
pb.setPrefWidth(300);
pb.progressProperty().bind(progress);
BorderPane borderPane = new BorderPane(pb);
gridPane.add(borderPane, 0, 0);
Scene scene = new Scene(gridPane);
setScene(scene);
sizeToScene();
show();
}
#Override
public void initialize(URL location, ResourceBundle resources) {
}
}
Example for usage (WorkingDialogTest.java):
package stackoverflow.progress;
import java.util.logging.Logger;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.ActionEvent;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class WorkingDialogTest extends Application {
private static final Logger LOG = Logger.getLogger(WorkingDialogTest.class.getName());
#Override
public void start(Stage primaryStage) {
Group group = new Group();
Scene scene = new Scene(group);
primaryStage.setTitle("Dialogs");
primaryStage.setWidth(600);
primaryStage.setHeight(400);
Button button = new Button("function");
button.setOnAction((ActionEvent e) -> {
WorkingDialog wd = new WorkingDialog("title", primaryStage);
new Thread(() -> {
int counter = 10;
for (int i = 0; i < counter; i++) {
try {
wd.progress.set(1.0 * i / (counter - 1));
Thread.sleep(1000); //<-------- do more useful stuff here
} catch (InterruptedException ex) {
}
}
wd.hideDialog();
}).start();
});
HBox hbox = new HBox(button);
group.getChildren().addAll(hbox);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
It looks like this:

ListView.scrollTo works slow with huge number of items

The scrollTo method in the code below works really slow. Is there any way to speed up it or may be some alternative variant? I need to display almost 100000 items in the application. Probably there are some alternative components. Thanks.
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
final ListView<String> listView = new ListView<>();
Button button = new Button("goto");
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
int i = 99998;
System.out.println("before scroll");
long startTime = System.currentTimeMillis();
listView.scrollTo(i);
long elapsedTime = System.currentTimeMillis() - startTime;
System.out.println(elapsedTime);
listView.getFocusModel().focus(i);
}
});
List<String> items = new ArrayList<>();
for (int i = 0; i < 100000; i++) {
items.add(UUID.randomUUID().toString());
}
listView.setItems(FXCollections.observableArrayList(items));
StackPane pane = new StackPane();
VBox vbox = new VBox();
vbox.getChildren().add(button);
vbox.getChildren().add(listView);
pane.getChildren().add(vbox);
stage.setScene(new Scene(pane));
stage.show();
}
}

Categories