0

We have a couple of buttons. When I first click a button it's get selected. When I click it back button get Deselected. we have a method that Deselects all selected button at once.

I try storing Boolean(object) in ArrayList. That I thought I might take object references and change object. ( in other words, reset flag) But it's not working at all.

Controller.java

import java.net.URL;
import java.util.ArrayList;
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.FlowPane;

public class Controller implements Initializable
{

    @FXML
    private FlowPane flowPane;

    //String 
    private ArrayList<String> list ;

    @Override
    public void initialize(URL location, ResourceBundle resources)
    {

        //Init String Array list
                list = new ArrayList<>();
                list.add("RED");
                list.add("GREEN");
                list.add("BLUE");
                list.add("YELLOW");
                list.add("WHITE");      
                list.add("DARK RED");
                list.add("DARK GREEN");
                list.add("DARK BLUE");
                list.add("DARK YELLOW");
                list.add("DARK WHITE");
    }

    //Add button
    @FXML
    private  void Add_btn(ActionEvent event)
    {   
        //Reading String Create nodes on flowPane
        for(String name : list) 
        {
            flowPane.getChildren().add(getBtn(name));
        }

    }
//Selected Button Array list
    private ArrayList<Button> selected_buttons = new ArrayList<>();

//Add Object to Button Array List
    private void add_to_list(Button btn)
    {
        selected_buttons.add(btn);
    }

//Remove Object from Button Array list
    private void remove_from_list(Button btn)
    {
        selected_buttons.remove(btn);
    }

//Reset click boolean
    private ArrayList<Boolean> reset_boolean = new ArrayList<>();

//Add bool to Arrylist
    private void add_to_reset_boolean(boolean bool) {
        reset_boolean.add(bool);
    }
//Remove bool in ArrayList
    private void remove_from_reset_boolean(boolean bool) {
        reset_boolean.remove(bool);
    }




//Returns java FX Button object
    private Button getBtn(String name)
    {
        Button btn = new Button(name);
        btn.setOnAction(new EventHandler<ActionEvent>()
        {   
            //Flag to check whether i click it first time or second time

            //private boolean first_click  = true;

            private Boolean first_click = new Boolean(true);
            @Override
            public void handle(ActionEvent event)
            {   
                //First time click,
                if(first_click)     
                { 
                    first_click = false;
                    //Show Selected
                    btn.setText(btn.getText()+" [Selected]");
                    //Add to selected Button Array list
                    add_to_list(btn);

                    add_to_reset_boolean(first_click);



                } else if(!first_click)     
                {
                    first_click = true;
                    //Remove Selected
                    btn.setText(btn.getText().replace(" [Selected]", ""));
                    //Remove from selected Button Array list
                    remove_from_list(btn);

                    remove_from_reset_boolean(first_click);
                }
            }


        });
        return btn;
    }
    //Reset Button
    @FXML
    private void reset_btn(ActionEvent event) 
    {   
        //On whatever remain in array list
        //On ever button in selected array list
        for(Button btn : selected_buttons) {

            //Remove Selected from Button
            btn.setText(btn.getText().replace(" [Selected]", ""));

        }
        //Every bool value
        for(Boolean bool : reset_boolean) { //I think im doing it wrong here
            bool = false;
        }
    }


}

Main.java

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application
{
    @Override
    public void start(Stage primaryStage) {
        try {


            Parent root = FXMLLoader.load(getClass().getResource("Window.fxml"));
            Scene scene = new Scene(root);          
            primaryStage.setScene(scene);           
            primaryStage.setMinWidth(350);
            primaryStage.show();

        } catch(Exception e) {
            System.err.println("Luncher Failed" +e);
        }
    }

    public static void main(String[] args) 
    {

        launch(args);

    }
}

Window.fxmxl

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.text.Font?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="booleanFix.Controller">
   <children>
      <FlowPane fx:id="flowPane" alignment="CENTER" columnHalignment="CENTER" hgap="10.0" layoutX="69.0" layoutY="60.0" prefHeight="61.0" prefWidth="482.0" vgap="20.0" />
      <Button layoutX="351.0" layoutY="330.0" mnemonicParsing="false" onAction="#reset_btn" prefHeight="47.0" prefWidth="117.0" text="Reset">
         <font>
            <Font size="20.0" />
         </font>
      </Button>
      <Button layoutX="164.0" layoutY="330.0" mnemonicParsing="false" onAction="#Add_btn" prefHeight="47.0" prefWidth="117.0" text="Add">
         <font>
            <Font size="20.0" />
         </font>
      </Button>
   </children>
</AnchorPane>

Buttons added to pane

Nodes Added to flow pane

Two button selected

Node Selected

Reset

enter image description here

Can't select on first click enter image description here

Double clicked

enter image description here

  • Note: I don't wanna want to load all Button to flow pane again because in my actual Application I have hundreds of button. Please don't suggest me that.
Max Vollmer
  • 8,412
  • 9
  • 28
  • 43
Ash
  • 71
  • 9
  • 2
    *But it's not working at all.* is not a good problem description – Scary Wombat Oct 29 '18 at 07:19
  • It's not working completely? I think u didn't change package name in Window.fxml _ fx:controller="booleanFix.Controller" _ Change it there or use a package name *booleanFix* – Ash Oct 29 '18 at 07:33
  • @Jai i pass by reference and change object value – Ash Oct 29 '18 at 07:38
  • Java is a **pass-by-value** language. You can never hold the reference of the `Boolean` this way. `for(Boolean bool : reset_boolean) { bool = false;}` does not work because `bool` is just a *temporary* variable of type `Boolean` used to *hold* the reference of the element in the list `reset_boolean`, and `bool = false` simply *reassigns* the reference of the boxed `false` value (i.e. equivalent to `Boolean.FALSE` as far as I know) into this temporary variable `bool`. Nothing is changed in the original referenced object. – Jai Oct 29 '18 at 08:00
  • A quick fix would be simply iterating through the list of buttons (i.e. `selected_buttons`) and then setting the `first_click` field of each button to `false`. – Jai Oct 29 '18 at 08:05
  • it didn't work with (Atomic boolean) as well So there is no fix? – Ash Oct 29 '18 at 08:06
  • 1
    `for(Button btn : selected_buttons) btn.first_click = false;` – Jai Oct 29 '18 at 08:12
  • How i add first_click variable to Button node? Should i make a class and extend from Button and add this variable there – Ash Oct 29 '18 at 08:18
  • Sorry, I forgot you declared that in the event handler. In this case, it's easier to subclass `Button` indeed. – Jai Oct 29 '18 at 08:34
  • @Jai Thank you so much man it really worked. It solved my other problems as well :) :) :) – Ash Oct 29 '18 at 09:18
  • 1
    Consider using [`ToggleButton`s](https://docs.oracle.com/javase/9/docs/api/javafx/scene/control/ToggleButton.html) They do not change the text when clicked (automatically), but they allow you to toggle between 2 states that also look different without the need to implement any of the logic yourself. BTW: Assignments to the loop variable of an enhanced for loop do not modify the collection and `Boolean` is an immutable type that cannot be used to wrap a value that may be changed... – fabian Oct 29 '18 at 09:49
  • @fabian thank you I understand it now :) :) – Ash Oct 29 '18 at 10:08
  • I rolled back your last edit. Please don't add things like *[Solved]* in the title, that is not how Stackoverflow works. If an answer solved your problem, mark it as such. – Max Vollmer Oct 29 '18 at 12:52
  • @MaxVollmer I just didn't want others to read my question and waste there time responding. I Will keep it in mind next time :) – Ash Oct 29 '18 at 13:09

1 Answers1

0

The solution is very simple.

Controller.java

package booleanFix;

import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.FlowPane;

public class Controller implements Initializable
{

    @FXML
    private FlowPane flowPane;

    //String 
    private ArrayList<String> list ;

    @Override
    public void initialize(URL location, ResourceBundle resources)
    {

        //Init String Array list
                list = new ArrayList<>();
                list.add("RED");
                list.add("GREEN");
                list.add("BLUE");
                list.add("YELLOW");
                list.add("WHITE");      
                list.add("DARK RED");
                list.add("DARK GREEN");
                list.add("DARK BLUE");
                list.add("DARK YELLOW");
                list.add("DARK WHITE");
    }

    //Add button
    @FXML
    private  void Add_btn(ActionEvent event)
    {   
        //Reading String Create nodes on flowPane
        for(String name : list) 
        {
            flowPane.getChildren().add(getBtn(name));
        }

    }
//Selected Button Array list
    private ArrayList<MyButton> selected_buttons = new ArrayList<>();

//Add Object to Button Array List
    private void add_to_list(MyButton btn)
    {
        selected_buttons.add(btn);
    }

//Remove Object from Button Array list
    private void remove_from_list(MyButton btn)
    {
        selected_buttons.remove(btn);
    }





//Returns java FX Button object
    private MyButton getBtn(String name)
    {
        MyButton btn = new MyButton(name);


        btn.setOnAction(new EventHandler<ActionEvent>()
        {   
            //Flag to check whether i click it first time or second time


            @Override
            public void handle(ActionEvent event)
            {   
                //First time click,
                if(btn.click)   
                { 
                    btn.click = false;
                    //Show Selected
                    btn.setText(btn.getText()+" [Selected]");

                    //Add to selected Button Array list
                    add_to_list(btn);





                } else if(!btn.click)   
                {   
                    btn.click = true;
                    //Remove Selected
                    btn.setText(btn.getText().replace(" [Selected]", ""));

                    //Remove from selected Button Array list
                    remove_from_list(btn);

                }
            }


        });
        return btn;
    }
    //Reset Button
    @FXML
    private void reset_btn(ActionEvent event) 
    {   
        //On whatever remain in array list
        //On ever button in selected array list
        for(MyButton btn : selected_buttons) {

            btn.click = true;

            btn.setText(btn.getText().replace(" [Selected]", ""));


        }

    }


}

MyButton Just need to create new Class that extends Button

package booleanFix;

import javafx.scene.control.Button;

public class MyButton extends Button
{
    public boolean click = true;

    //super(name); mean's Button.setText(name)
    public MyButton(String name)
    {
        super(name);

    }

}
Ash
  • 71
  • 9