JavaFX adding custom class to parent node - javafx

I'd appreciate any help at all, I have spent hours at this to no avail.
So I need to add an instance of a class I found online called GridDisplay to the Parent root, as I need the scene to then display this for me. But I also need to use the fxml file to set up the root and hence the scene. Here is what I have so far:
#FXML private BorderPane mainPanel = new BorderPane();
#FXML private TilePane tilePane = new TilePane();
#FXML private Pane topCanvas = new Pane();
#FXML private Pane leftCanvas = new Pane();
#FXML private Pane rightCanvas = new Pane();
#FXML private Pane bottomCanvas = new Pane();
#FXML private ScrollPane scrollPane = new ScrollPane();
#FXML private Button stacksButton = new Button();
#FXML private Button queueButton = new Button();
#FXML private Button stepStacksButton = new Button();
#FXML private Button stepQueueButton = new Button();
private MazeSolver solver;
private GridDisplay gridDisplay;
private ArrayList<String> maze;
private String fileLocation;
private int height;
private int width;
#Override
public void start(Stage primaryStage) throws IOException, InterruptedException
{
solver = new MazeSolver(fileLocation);
int[] dimensions = solver.getDimensions();
this.width = dimensions[0];
this.height = dimensions[1];
maze = solver.getMazeLayout();
primaryStage.setTitle("Maze Solver");
//this is the root which uses the fxml file and in turn sets up the scene
Parent root = FXMLLoader.load(getClass().getResource("MazeApp.fxml"));
Scene scene = new Scene(root);
//Represents the grid with Rectangles
gridDisplay = new GridDisplay(height, width);
gridDisplay.setMaze(maze);
mainPanel = new BorderPane();
//here i set the scroll pane as the mainPanel's content
mainPanel.setCenter(scrollPane);
//and then set the gridDisplay as the scroll panes content
scrollPane.setContent(gridDisplay.getDisplay());
//re paints the grid and its boxes
gridDisplay.createElements();
primaryStage.setScene(scene);
primaryStage.show();
}
The order in which I do any of these things makes no difference, it just never shows. I am always left with the window and a blank space where the maze should be, like so: https://www.dropbox.com/s/rqxa9dy2w9lw4tz/Screenshot%202015-03-11%2022.01.46.png?dl=0 (sorry about linking, cant post image directly).
Any help would be greatly appreciated.
EDIT:
My GridDisplay class:
public class GridDisplay{
private static final double ELEMENT_SIZE = 30;
private static final double GAP = ELEMENT_SIZE / 90;
private TilePane tilePane = new TilePane();
private Group display = new Group(tilePane);
private int nRows;
private int nCols;
private ArrayList<String> maze = null;
public GridDisplay(int nRows, int nCols)
{
tilePane.setStyle("-fx-background-color: rgba(255, 215, 0, 0.1);");
tilePane.setHgap(GAP);
tilePane.setVgap(GAP);
setColumns(nCols);
setRows(nRows);
}
public void setColumns(int newColumns)
{
nCols = newColumns;
tilePane.setPrefColumns(nCols);
createElements();
}
public void setRows(int newRows)
{
nRows = newRows;
tilePane.setPrefRows(nRows);
createElements();
}
public TilePane getDisplay()
{
return tilePane;
}
public void createElements()
{
tilePane.getChildren().clear();
for (int i = 0; i < nRows; i++) {
for (int j = 0; j < nCols; j++) {
if(maze==null)
tilePane.getChildren().add(createElement(Color.RED));
else
{
Color color = Color.WHITE;
if(Character.toString(maze.get(i).charAt(j)).equals("#"))
color = Color.BLACK;
if(Character.toString(maze.get(i).charAt(j)).equals("o"))
color = Color.GREEN;
if(Character.toString(maze.get(i).charAt(j)).equals("*"))
color = Color.RED;
tilePane.getChildren().add(createElement(color));
}
}
}
}
public void colorSolved()
{
tilePane.getChildren().clear();
for (int i = 0; i < nRows; i++) {
for (int j = 0; j < nCols; j++) {
if(maze==null)
tilePane.getChildren().add(createElement(Color.RED));
else
{
Color color = Color.WHITE;
if(Character.toString(maze.get(i).charAt(j)).equals("#"))
color = Color.BLACK;
if(Character.toString(maze.get(i).charAt(j)).equals("o"))
color = Color.GREEN;
if(Character.toString(maze.get(i).charAt(j)).equals("*"))
color = Color.RED;
tilePane.getChildren().add(createElement(color));
}
}
}
}
public void setMaze(ArrayList<String> maze)
{
this.maze = maze;
}
private Rectangle createElement(Color color) {
Rectangle rectangle = new Rectangle(ELEMENT_SIZE, ELEMENT_SIZE);
rectangle.setStroke(Color.BLACK);
rectangle.setFill(color);
return rectangle;
}
}
I cannot share the code for the xml as it will not paste into this window properly, here is a picture:
https://www.dropbox.com/s/27tbliubdlqdfzm/Screenshot%202015-03-12%2010.09.25.png?dl=0

Since your root is a BorderPane, you can just set the appropriate region in the code:
BorderPane root = FXMLLoader.load(getClass().getResource("MazeApp.fxml"));
Scene scene = new Scene(root);
//Represents the grid with Rectangles
gridDisplay = new GridDisplay(height, width);
gridDisplay.setMaze(maze);
ScrollPane scrollPane = new ScrollPane();
scrollPane.setContent(gridDisplay);
root.setCenter(scrollPane);
// etc

Related

Categories labal in BarChart surpass one another in JavaFx

I have a problem with the BarChart only at the first upload, the categories labels surpass one another. it looks like this:
and from the second load, everything looks good:
the code:
#FXML
private ComboBox<String> subDepList;
#FXML
private BarChart<String, Number> subDepChart;
#FXML
private Button showButton;
#FXML
private Label sdErrorMessage;
#FXML
void setSubDepBarChart(Event event) {
subDepChart.getData().clear();
sdErrorMessage.setVisible(false);
boolean flag = true;
int sdId = -1;
try {
sdId = Integer.parseInt(subDepList.getValue());
} catch (NumberFormatException e) {
sdErrorMessage.setVisible(true);
flag=false;
}
if (flag) {
SubDepartment sd = Hospital.getInstance().getRealSubDepartment(sdId);
//setting sub-department bar chart
XYChart.Series<String, Number> set1 = new XYChart.Series<>();
set1.getData().add(new XYChart.Data<String, Number>("Patients", sd.getPatients().size()));
set1.getData().add(new XYChart.Data<String, Number>("Doctors", sd.getDoctors().size()));
set1.getData().add(new XYChart.Data<String, Number>("Nurses", sd.getNurses().size()));
set1.getData().add(new XYChart.Data<String, Number>("Reports", sd.getReports().size()));
subDepChart.getData().addAll(set1);
}
}
How can i fix it?

Dynamically resizing and repositioning of buttons in GridPane

I am trying to create a window consisting of a left pane and a right pane included in a GridPane layout. I am drawing the bounding box of this two widgets and I can see that they are resizing when the main window of the application is resized. In the left pane a GridPane layout is used to add Buttons. While the left pane resizes properly the buttons inside the left pane do not resize and reposition once the left pane resizes. The complete code is listed below. Can anyone help ?
public class PlanesJavaFxApplication extends Application {
static class ToolbarPane extends Pane
{
public ToolbarPane() {
final HBox hbox = new HBox(5);
hbox.getChildren().add(new Text("TOP"));
this.getChildren().add(hbox);
}
}
static class LeftPane extends Pane
{
public LeftPane() {
final GridPane gridPane = new GridPane();
ColumnConstraints col1 = new ColumnConstraints();
col1.setPercentWidth(33);
ColumnConstraints col2 = new ColumnConstraints();
col2.setPercentWidth(33);
ColumnConstraints col3 = new ColumnConstraints();
col3.setPercentWidth(33);
gridPane.getColumnConstraints().addAll(col1, col2, col3);
Button selectButton = new Button("Select");
Button rotateButton = new Button("Rotate");
Button upButton = new Button("Up");
Button leftButton = new Button("Left");
Button rightButton = new Button("Right");
Button downButton = new Button("Down");
Button doneButton = new Button("Done");
gridPane.add(selectButton, 1, 0);
gridPane.add(rotateButton, 1, 1);
gridPane.add(upButton, 1, 2);
gridPane.add(leftButton, 0, 3);
gridPane.add(rightButton, 2, 3);
gridPane.add(downButton, 1, 4);
gridPane.add(doneButton, 1, 5);
//gridPane.prefWidth(300);
this.getChildren().add(gridPane);
}
}
static class RightPane extends Pane
{
public RightPane() {
final HBox hbox = new HBox(5);
hbox.getChildren().add(new Text("RIGHT"));
this.getChildren().add(hbox);
}
}
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
// TODO Auto-generated method stub
final GridPane gridPane = new GridPane();
ColumnConstraints col1 = new ColumnConstraints();
col1.setPercentWidth(40);
ColumnConstraints col2 = new ColumnConstraints();
col2.setPercentWidth(60);
gridPane.getColumnConstraints().addAll(col1, col2);
Pane leftPane = new LeftPane();
leftPane.setStyle("-fx-border-color: red");
Pane rightPane = new RightPane();
rightPane.setStyle("-fx-border-color: blue");
gridPane.add(leftPane, 0, 0);
gridPane.add(rightPane, 1, 0);
stage.setScene(new Scene(gridPane));
stage.show();
}
}
Simply add a binding between your LeftPane and your GridPane as below into LeftPane (at the end of the class):
static class LeftPane extends Pane {
public LeftPane() {
final GridPane gridPane = new GridPane();
ColumnConstraints col1 = new ColumnConstraints();
col1.setPercentWidth(33);
ColumnConstraints col2 = new ColumnConstraints();
col2.setPercentWidth(33);
ColumnConstraints col3 = new ColumnConstraints();
col3.setPercentWidth(33);
gridPane.getColumnConstraints().addAll(col1, col2, col3);
Button selectButton = new Button("Select");
Button rotateButton = new Button("Rotate");
Button upButton = new Button("Up");
Button leftButton = new Button("Left");
Button rightButton = new Button("Right");
Button downButton = new Button("Down");
Button doneButton = new Button("Done");
gridPane.add(selectButton, 1, 0);
gridPane.add(rotateButton, 1, 1);
gridPane.add(upButton, 1, 2);
gridPane.add(leftButton, 0, 3);
gridPane.add(rightButton, 2, 3);
gridPane.add(downButton, 1, 4);
gridPane.add(doneButton, 1, 5);
// In order to see the GridPane extends with the LeftPane, remove it further
gridPane.setGridLinesVisible(true);
// Those 2 following lines enable the gridpane to stretch/shrink according the LeftPane
gridPane.prefWidthProperty().bind(this.widthProperty());
gridPane.prefHeightProperty().bind(this.heightProperty());
//gridPane.prefWidth(300);
this.getChildren().add(gridPane);
}
}
You can also center your buttons for a better effect (GridPane.setValignment(Node pNode, VPos pVPos) and GridPane.setHalignment(Node pNode, HPos pHPos).
Some remarks (not applicable if the code you posted is an MCVE/SSCCE) :
Use FXML files as much as possible for a cleaner code
LeftPane could directly extends GridPane instead of Pane (in this case)
Based on your code, the problem is that the gridpane which hosts the buttons never changes it's shape. You need to add constraints and listeners to that gridpane as well.
here's an example:
public class PlanesJavaFxApplication extends Application {
static class ToolbarPane extends Pane {
public ToolbarPane() {
final HBox hbox = new HBox(5);
hbox.getChildren().add(new Text("TOP"));
this.getChildren().add(hbox);
}
}
static Button upButton = new Button("Up");
static class LeftPane extends Pane {
public LeftPane() {
final GridPane gridPane = new GridPane();
ColumnConstraints col1 = new ColumnConstraints();
col1.setPercentWidth(33);
ColumnConstraints col2 = new ColumnConstraints();
col2.setPercentWidth(33);
ColumnConstraints col3 = new ColumnConstraints();
col3.setPercentWidth(33);
gridPane.getColumnConstraints().addAll(col1, col2, col3);
Button selectButton = new Button("Select");
Button rotateButton = new Button("Rotate");
Button leftButton = new Button("Left");
Button rightButton = new Button("Right");
Button downButton = new Button("Down");
Button doneButton = new Button("Done");
gridPane.add(selectButton, 1, 0);
gridPane.add(rotateButton, 1, 1);
gridPane.add(upButton, 1, 2);
gridPane.add(leftButton, 0, 3);
gridPane.add(rightButton, 2, 3);
gridPane.add(downButton, 1, 4);
gridPane.add(doneButton, 1, 5);
//gridPane.prefWidth(300);
this.getChildren().add(gridPane);
}
}
static class RightPane extends Pane {
public RightPane() {
final HBox hbox = new HBox(5);
hbox.getChildren().add(new Text("RIGHT"));
this.getChildren().add(hbox);
}
}
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
// TODO Auto-generated method stub
final GridPane gridPane = new GridPane();
gridPane.setGridLinesVisible(true);
ColumnConstraints col1 = new ColumnConstraints();
col1.setPercentWidth(40);
ColumnConstraints col2 = new ColumnConstraints();
col2.setPercentWidth(60);
gridPane.getColumnConstraints().addAll(col1, col2);
Pane leftPane = new LeftPane();
leftPane.setStyle("-fx-border-color: red");
Pane rightPane = new RightPane();
rightPane.setStyle("-fx-border-color: blue");
stage.widthProperty().addListener((observable, oldValue, newValue) -> {
upButton.setPrefWidth(newValue.doubleValue() > oldValue.doubleValue() ? upButton.getWidth() + 5 : upButton.getWidth() - 5);
});
gridPane.add(leftPane, 0, 0);
gridPane.add(rightPane, 1, 0);
stage.setScene(new Scene(gridPane));
stage.show();
}
}

javafx button.onclick() not working

i am having a problem when i click on the button it doesn t work.
actually for the moment i am just asking that the button execute a system.out.println() just for the test. the name of the button is btndetailUser
listRechercheUser.setCellFactory(new Callback<ListView<User>, ListCell<User>>() {
#Override
public ListCell<User> call(ListView<User> p) {
ListCell<User> cell;
cell = new ListCell<User>() {
#Override
protected void updateItem(User user, boolean bln) {
super.updateItem(user, bln);
if (user != null) {
ImageView img;
String mm=user.getPath().trim();
if (mm.equals("fusee.png")){
img = new ImageView(new Image("mto/cr/images/"+mm));}
else{
img = new ImageView(new Image("mto/cr/images/mains-fonds.png"));
}
VBox vb = new VBox(10);
HBox hb = new HBox(20);
VBox vb1 = new VBox(20);
VBox vb3= new VBox(20);
vb1.getChildren().add(new Label(" "));
hb.setStyle("-fx-border-color: #C8C8C8 ;");
vb.setAlignment(Pos.CENTER);
VBox vb2 = new VBox(30);
vb.setAlignment(Pos.CENTER);
vb2.setAlignment(Pos.BASELINE_LEFT);
vb3.setAlignment(Pos.CENTER_RIGHT);
Label id = new Label(user.getId()+"id firas:");
Label username = new Label(user.getUsername()+" username firas:");
Label nom = new Label(user.getNom()+"nom firas:");
Label prenom = new Label(user.getPrenom()+"prenom firas:");
Button btndetailUser = new Button();
btndetailUser.setId("btndetailUser");
btndetailUser.setText("btndetailUser "+user.getId());
Image imageAccesProjet = new Image("mto/cr/images/enter.png");
ImageView enterIV= new ImageView(imageAccesProjet);
enterIV.setFitHeight(10);
enterIV.setFitWidth(10);
btndetailUser.setGraphic(enterIV);
btndetailUser.getStyleClass().add("buttonLogin");
System.out.println(btndetailUser.getText());
btndetailUser.setOnMouseClicked(
(MouseEvent event2) ->
System.out.println("firas"));
btndetailUser.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println(".handle()");
}
});
vb.getChildren().addAll(new Label(" "), img, new Label(" "),username);
vb2.getChildren().addAll(nom, prenom);
vb3.getChildren().addAll(btndetailUser);
hb.getChildren().addAll(vb1, vb, vb2,vb3);
setGraphic(hb);
}
}
};
return cell;
}
});
try something like,
btndetailUser.setOnAction(e -> {
System.out.println("freetext")
});

How to disable Button when TextField is empty?

In the following code I have a TextField and a Button. I need to disable the Button when ever the TextField is empty, so that I can avoid entering empty values to the database. How can I make the button disabled ?
private VBox addVBox() {
VBox vb1 = new VBox();
vb1.setPadding(new Insets(15, 20, 25, 20));
vb1.setSpacing(15);
vb1.setStyle("-fx-background-color: #333333;");
final Label label = new Label("Staff Details");
label.setFont(Font.font("Arial", FontWeight.BOLD, 20));
label.setTextFill(Color.WHITE);
TableColumn sub = new TableColumn("Staff Name");
sub.setMinWidth(400);
sub.setCellValueFactory(
new PropertyValueFactory<Staff, String>("subName"));
table.setItems(data);
table.getColumns().addAll(sub);
addSubName = new TextField();
addSubName.setPromptText("Staff Name");
addSubName.setPrefSize(200, 30);
final Button b2 = new Button("Add");
b2.setFont(Font.font("Calibri", FontWeight.BOLD, 17));
b2.setPrefSize(70, 30);
b2.setStyle(" -fx-base: #0066ff;");
b2.setTextFill(Color.BLACK);
b2.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
msg = addSubName.getText();
try {
enterStaff();
} catch ( ClassNotFoundException | SQLException ex) {
Logger.getLogger(AddStaff.class.getName()).log(Level.SEVERE, null, ex);
}
data.add(new Staff(addSubName.getText()));
addSubName.clear();
}
});
hb.getChildren().addAll(addSubName, b2);
hb.setSpacing(5);
vb1.getChildren().addAll(label, table, hb);
return vb1;
}
Similar to Uluk's answer, but using the Bindings fluent API:
btn.disableProperty().bind(
Bindings.isEmpty(textField1.textProperty())
.and(Bindings.isEmpty(textField2.textProperty()))
.and(Bindings.isEmpty(textField3.textProperty()))
);
Also note that, this new overloaded method of Bindings is added in JavaFX-8 and not avaliable in JavaFX-2.
The other way can be using bindings:
final TextField textField1 = new TextField();
final TextField textField2 = new TextField();
final TextField textField3 = new TextField();
BooleanBinding bb = new BooleanBinding() {
{
super.bind(textField1.textProperty(),
textField2.textProperty(),
textField3.textProperty());
}
#Override
protected boolean computeValue() {
return (textField1.getText().isEmpty()
&& textField2.getText().isEmpty()
&& textField3.getText().isEmpty());
}
};
Button btn = new Button("Button");
btn.disableProperty().bind(bb);
VBox vBox = new VBox();
vBox.getChildren().addAll(textField1, textField2, textField3, btn);
use textProperty() Listener for TextField
try this...
Button b1 = new Button("DELETE");
b1.setFont(Font.font("Calibri", FontWeight.BOLD, 17));
b1.setPrefSize(100, 30);
b1.setStyle(" -fx-base: #ffffff;");
b1.setTextFill(Color.BLACK);
b1.setDisable(true); // Initally text box was empty so button was disable
txt1.textProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> ov, String t, String t1) {
//System.out.println(t+"====="+t1);
if(t1.equals(""))
b1.setDisable(true);
else
b1.setDisable(false);
}
});

FX 2.x : How do I remove SplitPane?

I can add SplitPane in a XYChart by clicking the "Add Pane" button, and it works fine.
Now I would like to remove SplitPane by clicking the "Remove pane" button.
Here is full code
public class SplitPaneFxTest extends Application {
SplitPane splitPane = new SplitPane();
double percSplit = 0.50;
int idxSplit = 0;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(SplitPaneFxTest.class, args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("SplitPane Test");
Group root = new Group();
Scene scene = new Scene(root, 800, 650, Color.WHITE);
//CREATE THE SPLITPANE
splitPane.setPrefSize(scene.getWidth(), scene.getHeight());
splitPane.setOrientation(Orientation.VERTICAL);
//ADD LAYOUTS AND ASSIGN CONTAINED CONTROLS
BorderPane upperPane = new BorderPane();
HBox hbox = new HBox();
Button button1 = new Button("Add Pane");
hbox.getChildren().addAll(button1);
upperPane.setTop(hbox);
Button button2 = new Button("Remove Pane");
hbox.getChildren().addAll(button2);
upperPane.setTop(hbox);
BorderPane lowerPane = new BorderPane();
splitPane.getItems().addAll(upperPane);
splitPane.setDividerPosition(idxSplit, 0.70);
idxSplit++;
splitPane.getItems().addAll(lowerPane);
idxSplit++;
root.getChildren().add(splitPane);
primaryStage.setScene(scene);
primaryStage.show();
button1.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
BorderPane myborderpane = new BorderPane();
splitPane.getItems().addAll(myborderpane);
ObservableList<SplitPane.Divider> splitDiv = splitPane.getDividers();
System.out.println("splitDiv.size() "+splitDiv.size());
percSplit = 1/(double)(splitDiv.size()+1);
for (int i = 0; i< splitDiv.size(); i++) {
System.out.println("i "+i+" percSplit "+percSplit);
splitPane.setDividerPosition(i, percSplit);
percSplit += 1/(double)(splitDiv.size()+1);
}
}
});
}
}
Any help really appreciated.
You can store a list of inner panes and remove them based on this list:
final List<Pane> panes = new ArrayList<Pane>();
button1.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
BorderPane myborderpane = new BorderPane();
//adding
panes.add(myborderpane);
splitPane.getItems().addAll(myborderpane);
ObservableList<SplitPane.Divider> splitDiv = splitPane.getDividers();
System.out.println("splitDiv.size() " + splitDiv.size());
percSplit = 1 / (double) (splitDiv.size() + 1);
for (int i = 0; i < splitDiv.size(); i++) {
System.out.println("i " + i + " percSplit " + percSplit);
splitPane.setDividerPosition(i, percSplit);
percSplit += 1 / (double) (splitDiv.size() + 1);
}
}
});
button2.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
if (panes.size() > 0) {
// removing from both list and splitPane childs
Pane toDelete = panes.remove(0);
splitPane.getItems().remove(toDelete);
}
}
});
Also you can remove panes directly from ScrollPane.getChildren() but it can involve tricky and unreliable code to determine which pane to remove.

Resources