Delete button in TableView does not dissapear - java

I've got a little problem (it's really not that big of a deal but it annoys me), because after I delete a record from my table, I also want my delete button to disapear, right now it works like this:
BEFORE clicking the DELETE button:
AFTER clicking first record's DELETE button:
Also, this is the function that I'm using to handle this event:
private class ButtonCell extends TableCell<Record, Boolean> {
final Button cellButton = new Button("Delete");
ButtonCell(){
cellButton.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent t){
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Confirmation Dialog");
alert.setHeaderText("Delete the entire row?");
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK){
Animal currentAnimal = (Animal) ButtonCell.this.getTableView().getItems().get(ButtonCell.this.getIndex());
data.remove(currentAnimal);
cellButton.setVisible(false);
}
}
});
}
//Display button if the row is not empty
#Override
protected void updateItem(Boolean t, boolean empty) {
super.updateItem(t, empty);
if(!empty){
setGraphic(cellButton);
}
}
}

Try this:
#Override
protected void updateItem(Boolean t, boolean empty) {
super.updateItem(t, empty);
if(empty){
setGraphic(null);
} else {
setGraphic(cellButton);
}
}

Related

How to reference cell data on CellFactory?

I have a TableView where the last column is an "Action" column, containing a custom ActionBox object, with buttons for several actions. To add behaviour to this ActionBox, I need to pass a Data object to it. However, I don't know how to reference the object.
class TableViewWithActionColumn() {
#FXML TableColumn<Data, Void> actionColumn;
public TableViewWithActionColumn() {
// Code for loading custom component...
}
#FXML
public void initialize() {
populateActionColumn();
}
private void populateActionColumn() {
Callback<TableColumn<Data, Void>, TableCell<Data, Void>> cellFactory = new Callback<TableColumn<Data, Void>, TableCell<Data, Void>>() {
#Override
public TableCell<Data, Void> call(final TableColumn<Data, Void> param) {
return new TableCell<Data, Void>() {
private final ActionBox actionBox = new ActionBox();
#Override
public void updateItem(Void item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
setGraphic(actionBox);
}
}
};
}
};
actionColumn.setCellFactory(cellFactory);
}
}
I assumed that the reference to the object was in Void item, so I tried replacing all occurrences of Void with Data, and doing setGraphic(new ActionBox(item));, but this led to a NullPointerException, so I suppose that's not the right way to do it. So, how do I reference row's data in CellFactory context?
TableCell has a getTableRow() method, that gives you a reference to the TableRow that contains the cell. The TableRow is itself a cell implementation, so you can call its getItem() method to get the data represented by the row.
In context (and removing all the unnecessary boilerplate from your code):
private void populateActionColumn() {
actionColumn.setCellFactory(col -> new TableCell<Data, Void>() {
private final ActionBox actionBox = new ActionBox();
#Override
public void updateItem(Void item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
Data rowData = getTableRow().getItem();
// ... something like: actionBox.setData(rowData) ;
setGraphic(actionBox);
}
}
});
}

Click event on ImageView inside TableCell in JavaFX

I have a JavaFX TableView populated with many TableColumns, one of which is matImageColumn. The code for it looks like:
matImageColumn.setCellFactory(new Callback<TableColumn<CustomObject, ImageView>, TableCell<CustomObject, ImageView>>() {
#Override
public TableCell call(final TableColumn<CustomObject, ImageView> param) {
final TableCell<CustomObject, ImageView> cell = new TableCell<CustomObject, ImageView>() {
ImageView img = new ImageView();
#Override
public void updateItem(ImageView item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
setText(null);
} else {
CustomObject co = getTableView().getItems().get(getIndex());
img = co.getImageViewOfMat();
setGraphic(img);
setText(null);
}
}
};
return cell;
}
});
Now as it is, I am looking to include a click event on my imageview but I am clueless from where to start.Can you show me possible solutions to this issue? Thanks in advance.

Is there a way to change the contents of a ComboBoxTableCell depending on the row and column that is being edited?

I am using a JavaFX tableview that has 5 columns (Data Type of Column): Task Id (int), Task Name (String), Task Description (String), Status (String) and Remark (String). Now, I am loading the data from a database that has the same columns and what I'm trying to do is when the user clicks on the task status column in the software the column cell changes to a Combobox (String) but the list of statuses that are displayed in the Combobox should be different depending on the selected item that the user is trying to edit (aka the status of the task)
I have tried creating a new cellFactory in the OnEdit of the column and I have also tried to override the update item method and using a boolean variable I would set whether to set the graphic to a Combobox or not
myStatusColumn.setOnEditStart(new EventHandler<TableColumn.CellEditEvent<Task, String>>() {
#Override
public void handle(TableColumn.CellEditEvent<Task, String> event) {
try {
dataBeingEdited = true;
Task task = myTasksTable.getSelectionModel().getSelectedItem();
statuses = Login.dbHandler.getStatuses(task.getTaskTypeID());
myStatusColumn.setCellFactory(new Callback<TableColumn<Task, String>, TableCell<Task, String>>() {
#Override
public TableCell<Task, String> call(TableColumn<Task, String> param) {
return new TableCell<Task,String>(){
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if(empty)
setGraphic(null);
else
{
if(dataBeingEdited)
{
ComboBox<String> comboBox = new ComboBox<>(statuses);
setGraphic(comboBox);
}
}
}
};
}
});
} catch (SQLException e) {
e.printStackTrace();
}
}
});
I expect the output to be a Combobox when I double click on the status column but I am not getting a Combobox to appear and when I get
so far I have not found a way to directly use the ComboBoxTableCell class but what I did is redesigned my own using the CellFactory. What I did was before returning the Cell created in the CellFactory I set an onMouseClickedListner that will check for a double click and when the user double clicks I would get the selected item from the table and set the graphic to be a Combobox with values that depend on the row selected and the column clicked
and then I set an onKeyPressedListener that will change the item selected and then refresh the table and update the database
myStatusColumn.setCellFactory(new Callback<TableColumn<Task, String>, TableCell<Task, String>>() {
#Override
public TableCell<Task, String> call(TableColumn<Task, String> param) {
ComboBox<String> box = new ComboBox<>();
TableCell<Task, String> cell = new TableCell<Task, String>() {
#Override
protected void updateItem(String item, boolean empty) {
if (empty)
setGraphic(null);
else {
setEditable(false);
setText(item);
}
}
};
cell.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if(event.getButton().equals(MouseButton.PRIMARY))
{
Task task = myTasksTable.getSelectionModel().getSelectedItem();
if(task!=null)
box.setItems(FXCollections.observableArrayList(task.getStatuses()));
cell.setEditable(true);
}
if(event.getClickCount()==2 && cell.isEditable() ) {
box.getSelectionModel().select(0);
cell.setText(null);
cell.setGraphic(box);
}
}
});
cell.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if(event.getCode().equals(KeyCode.ENTER))
{
try {
TaskLog taskLog = (TaskLog) myTasksTable.getSelectionModel().getSelectedItem();
if(taskLog != null) {
taskLog.setStatues(box.getSelectionModel().getSelectedItem());
taskLog.setStatuesID(Login.dbHandler.getStatusID(taskLog.getStatues()));
System.out.println(taskLog.getStatues());
Login.dbHandler.addNewTaskLog(taskLog);
cell.setEditable(false);
myTasksTable.refresh();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
});
return cell;
}
});

How to change text alignment of a combo box items in javafx?

I have a Combo Box in my app . I added some items as string to it . Items have left alignment . I want the right alignment . I searched a lot but i cant find anything.
Thanks.
I figured out the following solution, although I'm not sure if it's a good one:
For button cell:
box.setButtonCell(new ListCell<String>() {
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
setText(item);
setAlignment(Pos.CENTER_RIGHT);
Insets old = getPadding();
setPadding(new Insets(old.getTop(), 0, old.getBottom(), 0));
}
}
});
For popup list view:
box.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
#Override
public ListCell<String> call(ListView<String> list) {
return new ListCell<String>() {
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
setText(item);
setAlignment(Pos.CENTER_RIGHT);
setPadding(new Insets(3, 3, 3, 0));
}
}
};
}
});

How to get row value inside updateItem() of CellFactory

ageColumn.setCellFactory(param -> new TableCell<Person, String>(){
#Override
protected void updateItem(String item, boolean empty) {
param.getCellFactory().
super.updateItem(item, empty);
setText(empty ? null : String.valueOf(item));
if(person.getName.equals("MATEUS")) {
setStyle("-fx-background-color: red;");
}
}
});
How to get this "Person" which is the row value from the Table? I can only get the value from the cell, but not the entire object.
You can do
Person person = getTableView().getItems().get(getIndex());
You can also do
Person person = (Person) getTableRow().getItem();
but this is less desirable (in my opinion) because getTableRow() returns a raw type, and consequently it requires the unchecked downcast.
Obviously either of these only works if empty is false, so they should be inside a check for that:
ageColumn.setCellFactory(param -> new TableCell<Person, String>(){
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setStyle("");
} else {
setText(item);
Person person = getTableView().getItems().get(getIndex());
if(person.getName.equals("MATEUS")) {
setStyle("-fx-background-color: red;");
} else {
setStyle("");
}
}
}
});

Categories