1

Referring to question JavaFX TableView custom cell rendering split menu button, i'm able to render split menu button in every row. I've updated my code as suggested by James_D and in the answer by Keyur Bhanderi. The question is about get value of the row where split menu is located without selecting row before click.

Update: Added images to view output

The images below show the output, every button i click.

Row selected click frist action button

Row selected click second action button

Updated SplitMenuCellFactory.java

package com.example.splimenubtn;

import java.util.List;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.util.Callback;

public class SplitMenuCellFactory<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> {

 private List<MenuItemFactory<T>> menuItems;

 public SplitMenuCellFactory() {}

 public SplitMenuCellFactory(List<MenuItemFactory<T>> items) {
  menuItems = items;
 }

 @Override
 public TableCell<S, T> call(TableColumn<S, T> param) {
  return new TableCell<S, T>() {
   @Override
   public void updateItem(T item, boolean empty) {
    super.updateItem(item, empty);
    if (empty) {
     setGraphic(null);
     setText(null);
    } else {
     setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
     if (getTableRow() != null) {
      setGraphic(new SplitMenuButtonFactory<>(menuItems, getTableRow().getIndex()).buildButton());
     }
    }
   }
  };
 }
}

Update, adding missing class

SplitMenuButtonFactory.java

package com.example.splimenubtn;

 import java.util.List;
 import javafx.scene.control.MenuItem;
 import javafx.scene.control.SplitMenuButton;

 public class SplitMenuButtonFactory<T> {

  private List<MenuItemFactory<T>> menuItems;
  private int rIndex = 0;

  public SplitMenuButtonFactory(List<MenuItemFactory<T>> items) {
   menuItems = items;
  }

  public SplitMenuButtonFactory(List<MenuItemFactory<T>> items, int rI) {
   menuItems = items;
   rIndex = rI;
  }

  public SplitMenuButton buildButton() {
   SplitMenuButton menuBtn = new SplitMenuButton();
   // menuBtn.getItems().addAll(menuItems);
   for (MenuItemFactory<?> mIF : menuItems) {
    MenuItem btn = mIF.setRowIndex(rIndex).buildMenuItem();
     if (mIF.isDefault()) {
     menuBtn.setText(btn.getText());
     menuBtn.setOnAction(btn.getOnAction());
    }
    menuBtn.getItems().add(btn);
   }
  return menuBtn;
 }
}

MenuItemsFactory.java

package com.example.splimenubtn;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableView;

public class MenuItemFactory<S> {

 private MenuItemActions itemType;
 private String itemLbl;
 private TableView<S> table;
 private boolean defaultAction;
 private int rIndex = 0;

 public MenuItemFactory(MenuItemActions itemType, String itemLabel, boolean dA) {
  this.itemType = itemType;
  itemLbl = itemLabel;
  defaultAction = dA;
 }

 public MenuItemFactory(MenuItemActions itemType, String itemLabel, TableView<S> t, boolean dA) {
  this.itemType = itemType;
  itemLbl = itemLabel;
  defaultAction = dA;
  table = t;
 }

 public MenuItemFactory<S> setDataList(TableView<S> t) {
  table = t;
  return this;
 }

 public boolean isDefault() {
  return defaultAction;
 }

 public MenuItemFactory<S> setRowIndex(int rI) {
  rIndex = rI;
  return this;
 }

 public MenuItem buildMenuItem() {
  MenuItem mI = new MenuItem();
  switch (itemType) {
   case DETAILS:
    mI.setText(itemLbl);
    mI.setOnAction(handleDetails());
   break;
  case EDIT:
    mI.setText(itemLbl);
    mI.setOnAction(handleEdit());
   break;
   case DELETE:
    mI.setText(itemLbl);
    mI.setOnAction(handleDelete());
   break;
   default:
   break;
  }
  return mI;
 }

 private EventHandler<ActionEvent> handleDetails() {
  return new EventHandler<ActionEvent>() {
   @Override
   public void handle(ActionEvent aE) {
    System.out.println("*** DETAIL REQUEST ***");
   }
  };
 }

 private EventHandler<ActionEvent> handleEdit() {
  return new EventHandler<ActionEvent>() {
   @Override
   public void handle(ActionEvent aE) {
    System.out.println("*** EDIT REQUESTED ***");
    table.getSelectionModel().select(rIndex);
    System.out.println("*** " + table.getSelectionModel().getSelectedItem().toString() + " ***");
   }
  };
 }

 private EventHandler<ActionEvent> handleDelete() {
  return new EventHandler<ActionEvent>() {
   @Override
   public void handle(ActionEvent aE) {
    System.out.println("*** DELETE REQUESTED ***");
    System.out.println("*** " + table.getSelectionModel().getSelectedItem().toString() + " ***");
   }
  };
 }
}

But when i click on the button, i'm getting always last value.

How can i get the object in the row where button is?

Any help or suggestion that point me to right direction is appreciated.

1 Answer 1

1

Simply use the TableCell to retrieve the value in the onAction event handler (or whatever you use in the product of the SplitMenuButtonFactory you're not showing to us).

Simplified example

public static SplitMenuButton createSplitMenuButton(final TableCell cell) {
    SplitMenuButton result = new SplitMenuButton();

    result.setOnAction(evt -> {
        TableRow row = cell.getTableRow();
        System.out.println("row item: " +row.getItem());
    });

    return result;
}

Furthermore it's better to reuse the SplitMenuButton in the cell and updating it instead of recerating it every time the cell item changes.

@Override
public TableCell<S, T> call(TableColumn<S, T> param) {
    return new TableCell<S, T>() {

        private final SplitMenuButton button = createSplitMenuButton(this);

        {
            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
        }

        @Override
        public void updateItem(T item, boolean empty) {
            super.updateItem(item, empty);

            if (empty) {
                setGraphic(null);
            } else {
                updateMenuButton(button, item); // placeholder for updating the button according to the new item

                setGraphic(button);
            }
        }
    };
}
Sign up to request clarification or add additional context in comments.

1 Comment

you can view the SplitMenuButtonFactory in the linked question stackoverflow.com/questions/44577364

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.