0

So I´m building a warband calculator for a tabletop game and currently it looks like this

enter image description here

What I wanna do is that when I click on a "add" button it copies that unit/creature over to the tableview on the right side(So if I click on the "add" button on the Zombie row, a zombie gets copied over the tableview on the right).

The problem is I can only make it work if you select the row THEN click the button, but I want to be able to rely solely on the button. I think the problem is that I use "getSelectionModel().getSelectedItem()" in the button class to get the object to be copied over, But I cant find any other way to do it.

The relevant code parts from the main class

//Creates the lists

  ObservableList<Unit> rightSideList = FXCollections.observableArrayList();

  ObservableList<Unit> leftSideList = FXCollections.observableArrayList();

  // Puts some test data in the lists

  public Main() {

      rightSideList.add(new Unit("Skeleton",5,4,9,4,1,6,9));
      rightSideList.add(new Unit("Ghoul",6,4,010,4,1,6,7));
      rightSideList.add(new Unit("Zombie",4,5,1,3,1,6,5));
      rightSideList.add(new Unit("Wraith",4,5,19,3,1,6,5));
      rightSideList.add(new Unit("Spectre",4,5,1,3,1,6,5));

      leftSideList.add(new Unit("Skeleton",5,4,0,4,1,6,9));

  }
          //Creates the tables

      final TableView<Unit> table1 = new TableView<>(
            rightSideList

              );
      final TableView<Unit> table2 = new TableView<>(     
              leftSideList

  );          
//Defines the table columns

      //Columns for table 1

      TableColumn<Unit,String> unitNameCol = new TableColumn<>("Unit");
      unitNameCol.setCellValueFactory(new PropertyValueFactory("unitName"));
      unitNameCol.setMinWidth(100);
      TableColumn<Unit,Integer> speedCol = new TableColumn<>("Spd");
      speedCol.setCellValueFactory(new PropertyValueFactory("speed"));
      TableColumn<Unit,Integer> meleeCol = new TableColumn<>("Me");
      meleeCol.setCellValueFactory(new PropertyValueFactory("melee"));
      TableColumn<Unit,Integer> rangedCol = new TableColumn<>("Ra");
      rangedCol.setCellValueFactory(new PropertyValueFactory("ranged"));
      TableColumn<Unit,Integer> defenseCol = new TableColumn<>("Def");
      defenseCol.setCellValueFactory(new PropertyValueFactory("defense"));
      TableColumn<Unit,Integer> attackCol = new TableColumn<>("Att");
      attackCol.setCellValueFactory(new PropertyValueFactory("attack"));
      TableColumn<Unit,Integer> toughnessCol = new TableColumn<>("To");
      toughnessCol.setCellValueFactory(new PropertyValueFactory("toughness"));
      TableColumn<Unit,Integer> costCol = new TableColumn<>("Cost");
      costCol.setCellValueFactory(new PropertyValueFactory("cost"));
      TableColumn<Unit, Boolean> actionCol = new TableColumn<>("Action");
        actionCol.setSortable(false);
        actionCol.setMinWidth(35);

            // define a simple boolean cell value for the action column so that the column will only be shown for non-empty rows for table 1
        actionCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Unit, Boolean>, ObservableValue<Boolean>>() {
          @Override public ObservableValue<Boolean> call(TableColumn.CellDataFeatures<Unit, Boolean> features) {
            return new SimpleBooleanProperty(features.getValue() != null);
          }
        });

        // create a cell value factory with an add button for each row in the table for table 1
        actionCol.setCellFactory(new Callback<TableColumn<Unit, Boolean>, TableCell<Unit, Boolean>>() {
          @Override public TableCell<Unit, Boolean> call(TableColumn<Unit, Boolean> unitBooleanTableColumn) {
            return new AddUnitCell(mainStage, table1);
          }
        });

And here is the button class

/** A table cell containing a button for adding a unit */
  private class AddUnitCell extends TableCell<Unit, Boolean> {
    // a button for adding a new Unit.
    final Button addButton       = new Button("Add");
    // pads and centers the add button in the cell.
    final StackPane paddedButton = new StackPane();


    /**
     * AddUnitCell constructor
     * @param stage the stage in which the table is placed.
     * @param table the table to which a unit can be added.
     */
    AddUnitCell(final Stage stage, final TableView<Unit> table) {
      paddedButton.setPadding(new Insets(3));
      paddedButton.getChildren().add(addButton);

      addButton.setOnAction(new EventHandler<ActionEvent>() {
        @Override public void handle(ActionEvent actionEvent) {

            Unit selectedUnit = table.getSelectionModel().getSelectedItem();
            leftSideList.add(selectedUnit);
        }
      });
    }

    /** places an add button in the row only if the row is not empty. */
    @Override protected void updateItem(Boolean item, boolean empty) {
      super.updateItem(item, empty);
      if (!empty) {
        setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
        setGraphic(paddedButton);
      } else {
        setGraphic(null);
      }
    }
  }

If you need to check in detail here is a link to the projects repository

https://github.com/MagnusLindstrom88/Star-Struck-City-Warband-Calculator/blob/master/src/application/Main.java

0

2 Answers 2

1

Instead of

Unit selectedUnit = table.getSelectionModel().getSelectedItem();

in the button event handler's handle() method, do

Unit selectedUnit = table.getItems().get(getIndex());
Sign up to request clarification or add additional context in comments.

Comments

1

Instead of relying on the selection model to get the item, you should get the item from the TableRow:

Unit selectedUnit = (Unit) getTableRow().getItem();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.