How to set bold true for some row in TableView JavaFX - javafx

I have TableView<TypeReport> tv and column
tc_name.setCellValueFactory(new PropertyValueFactory<>("name"));
I want rows to be bold if date in cell of tc_name does not starts with " ".
I use:
tv.setRowFactory(new Callback<TableView<TypeReport>, TableRow<TypeReport>>() {
#Override
public TableRow<TypeReport> call(TableView<TypeReport> param) {
return new TableRow<TypeReport>() {
#Override
protected void updateItem(TypeReport item, boolean empty) {
if (item==null) {
setStyle("");
} else {
String res=item.getName();
if (res.startsWith(" ")){}
else
setStyle("-fx-font-weight: bold");
}
}
};
}
});
When I open app, required rows are bold, but when I scroll, some differ rows are bold.

You need to remove the style for rows whose item's name starts with " ". (Note you also need to call super.updateItem(...)):
#Override
protected void updateItem(TypeReport item, boolean empty) {
super.updateItem(item, empty);
if (item==null) {
setStyle("");
} else {
String res=item.getName();
if (res.startsWith(" ")) {
setStyle("");
} else
setStyle("-fx-font-weight: bold");
}
}
or, equivalently (but with less code):
#Override
protected void updateItem(TypeReport item, boolean empty) {
super.updateItem(item, empty);
if (item==null || item.getName().startsWith(" ")) {
setStyle("");
} else {
setStyle("-fx-font-weight: bold");
}
}

Related

JavaFX: add contextmenu to TableView cell

I'm trying to add a context menu for every individual cell in a column, that gets activated by rightclicking on the cell. The menuitems would also depend on the cell clicked.
I would think using a cell factory would be the best way, but I cant figure out how to do it.
Edit: This is my implementation for one of my columns. setText in updateItem() adds the text to my column, but I want to add it as a label, how should I do that?
moColumn = new TableColumn<>("Maandag");
moColumn.setSortable(false);
moColumn.setCellValueFactory(new PropertyValueFactory<>("Mo"));
getColumns().add(moColumn);
moColumn.setCellFactory(new Callback<TableColumn<RowData, Label>, TableCell<RowData, Label>>() {
#Override
public TableCell<RowData, Label> call(TableColumn<RowData, Label> col) {
final TableCell<RowData, Label> cell = new TableCell<RowData, Label>() {
#Override
protected void updateItem(Label item, boolean empty) {
super.updateItem(item, empty);
if(empty){
setText(null);
} else {
setText(item.getText());
}
}
};
//cell.textProperty().bind(cell.getItem().textProperty());
cell.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if(event.getButton() == MouseButton.SECONDARY){
ContextMenu contextMenu = new ContextMenu();
MenuItem menuItem = new MenuItem(cell.getText());
contextMenu.getItems().add(menuItem);
cell.setContextMenu(contextMenu);
}
}
});
return cell;
}
});
Edit: How can I right click on a cell in tableview in Javafx (fxml)?
I've found this, but the link to the blog isn't working anymore...
Changed:
#Override
protected void updateItem(Label item, boolean empty) {
super.updateItem(item, empty);
if(empty){
setText(null);
} else {
setText(item.getText());
}
}
To:
#Override
protected void updateItem(Label item, boolean empty) {
super.updateItem(item, empty);
if(empty){
setText(null);
} else {
setGraphic(item);
}
}

Javafx: Table Column commit on Button click

I have method that make a TableColumn editable that I made according to this tutorial, with the two changes recommended in this question witch are changing focusedProperty with setOnAction and add binding. The method is like this:
public static <T> void setAutoCompleteTableColumn(TableColumn<T,String> column, BiConsumer<T, String> field, String type, BiConsumer handleUpdates, List autoComplete){
column.setCellFactory(param -> {
return new TableCell<T, String>(){
private TextField textField;
#Override
public void startEdit() {
super.startEdit();
createTextField();
setText(null);
setGraphic(textField);
textField.selectAll();
}
#Override
public void cancelEdit() {
super.cancelEdit();
setText((String) getItem());
setGraphic(null);
}
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (textField != null) {
textField.setText(getString());
}
setText(null);
setGraphic(textField);
} else {
setText(getString());
setGraphic(null);
}
}
}
private void createTextField(){
textField = new TextField(getString());
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap()* 2);
textField.setOnAction(event ->{
if(textField.getText() != ""){
commitEdit(textField.getText());
}
});
AutoCompletionBinding<T> binding = TextFields.bindAutoCompletion(textField,autoComplete);
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
};
});
column.setOnEditCommit(event -> {
T model = event.getRowValue();
if (!event.getNewValue().isEmpty()) {
Cloner cloner = new Cloner();
final T oldModel = cloner.deepClone(model);
//Update the old value with the new value
field.accept(model, event.getNewValue());
//Retrieve changes
handleUpdates.accept(oldModel, model);
}
});
}
I use this method in the controller like this:
TableColumn<Purchase, String> nameColumn = new TableColumn<>();
setAutoCompleteTableColumn(nameColumn, (p,s) -> validatePurchaseEdit(p,s), "text", (o, n) -> updateTracker(o, n), appState.items);
I have a button click event that switch the TableView editable to false.
For some reason when this event is executed the current cell that I am editing does commit edit but an other cell(a random one) switches to edit mode. Can some one explain what is happening, and how can I make all cells commit edit?

JavaFX editable ComboBox in a table view

I am using a editable ComboBox cell in a table view. Here is my ComboBox cell class
public class ComboBoxCell extends TableCell<ClassesProperty, String> {
private ComboBox<String> comboBox;
public ComboBoxCell() {
}
#Override
public void startEdit() {
super.startEdit();
if (comboBox == null) {
createComboBox();
}
setGraphic(comboBox);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
Platform.runLater(new Runnable() {
#Override
public void run() {
comboBox.requestFocus();
comboBox.getEditor().requestFocus();
comboBox.getEditor().selectAll();
}
});
}
#Override
public void cancelEdit() {
super.cancelEdit();
setText(String.valueOf(getItem()));
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (comboBox != null) {
comboBox.setValue(getString());
}
setGraphic(comboBox);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
} else {
setText(getString());
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
}
private void createComboBox() {
// ClassesController.getLevelChoice() is the observable list of String
comboBox = new ComboBox<>(ClassesController.getLevelChoice());
comboBox.setEditable(true);
comboBox.setMinWidth(this.getWidth() - this.getGraphicTextGap()*2);
comboBox.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent t) {
if (t.getCode() == KeyCode.ENTER) {
commitEdit(comboBox.getSelectionModel().getSelectedItem());
} else if (t.getCode() == KeyCode.ESCAPE) {
cancelEdit();
}
}
});
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
}
The problem I need to press three clicks on the table cell to get the text field of the combo box to edit the contents. Is there a way to make it in two clicks? I even used Platforn runlater but when I try to edit a cell at first time it takes three mouse clicks but at the second time only two clicks.
In your overridden cell.startEdit() method, Add a ListView with a textfield, then add this listview to setGraphic. This will show the listview directly once the row is selected and the cell is clicked, the listview will be inside the tablecell, I am yet to find a way to make it as a popup

JavaFX tab through editable cells

I have defined my own editable cell for a TableView. Everything works great but I want to be able to tab through the cells. Say I'm in cell [2,2] on a tab press I want the selected cell to go to [3,2]. Is this possible? How should I go about achieving this? Should I add a listener to the TableCell or the TableColumn?
Here is my custom TableCell
class EditingCell extends TableCell<Student, String> {
private TextField textField;
public EditingCell(Assignment assign) {
this.setTooltip(new Tooltip(assign.getMaxPoints() + " pts max"));
}
#Override
public void startEdit() {
if (!isEmpty()) {
super.startEdit();
createTextField();
setText(null);
setGraphic(textField);
textField.selectAll();
}
}
#Override
public void cancelEdit() {
super.cancelEdit();
setText((String) getItem());
setGraphic(null);
}
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (textField != null) {
textField.setText(getString());
}
setText(null);
setGraphic(textField);
} else {
setText(getString());
setGraphic(null);
}
}
}
private void createTextField() {
textField = new TextField(getString());
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap()* 2);
textField.focusedProperty().addListener(new ChangeListener<Boolean>(){
#Override
public void changed(ObservableValue<? extends Boolean> arg0,
Boolean arg1, Boolean arg2) {
if (!arg2) {
commitEdit(textField.getText());
}
}
});
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
}
You can achieve this by adding a KeyListener to your textField. Try adding the following code to your createTextField()
textField.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent t) {
if (t.getCode() == KeyCode.ENTER) {
commitEdit(Integer.parseInt(textField.getText()));
} else if (t.getCode() == KeyCode.ESCAPE) {
cancelEdit();
} else if (t.getCode() == KeyCode.TAB) {
commitEdit(Integer.parseInt(textField.getText()));
TableColumn nextColumn = getNextColumn(!t.isShiftDown());
if (nextColumn != null) {
getTableView().edit(getTableRow().getIndex(), nextColumn);
}
}
}
});
There are a few more things that you will have to take care of. For a complete example, please follow
https://gist.github.com/abhinayagarwal/9383881

How to change the row color based on data that can change in a tableview?

I am writing a podcast player and have a list of files that I display.
The user can double click an entry and that files play. If they select another one. I don’t know what has been selected in the list. The idea is to highlight the file that is playing in a different color. With still keeping the ability to select another file (don’t want to lose that functionality). Most audio players work on the same principle.
I had a look at this JavaFX tableview colors and this changes the color of the row based on data. But if the data changes the row color do not refresh as the data changes.
I have a table with cell factory and based on the variable "isSelectedFile" I set the cell style.
If the isSelectedFile=True at load time all is ok but once I change the data while the rows are loaded into the tableview it doesn't refresh.
My cell factory is as follows:
entryDisplayNameColumn.setCellFactory(new Callback<TableColumn<PlaylistEntry, String>, TableCell<PlaylistEntry, String>>() {
#Override
public TableCell call(TableColumn p) {
TableCell cell = new TableCell<Task, Object>() {
#Override
public void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
setText(empty ? null : getString());
setGraphic(null);
TableRow currentRow = getTableRow();
PlaylistEntry ple = currentRow == null ? null : (PlaylistEntry) currentRow.getItem();
if (ple != null) {
clearPriorityStyle();
setPriorityStyle(ple.isSelectedFile());
}
}
#Override
public void updateSelected(boolean upd) {
super.updateSelected(upd);
System.out.println("is update");
}
private void clearPriorityStyle() {
ObservableList<String> styleClasses = getStyleClass();
styleClasses.remove("priorityLow");
styleClasses.remove("priorityMedium");
styleClasses.remove("priorityHigh");
}
private void setPriorityStyle(boolean activeValue) {
if (activeValue) {
getStyleClass().add("priorityLow");
} else {
getStyleClass().add("priorityMedium");
}
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
};
return cell;
}
});
My CSS:
.priorityLow {
-fx-control-inner-background: snow;
-fx-accent: derive(-fx-control-inner-background, -40%);
-fx-cell-hover-color: derive(-fx-control-inner-background, -20%);
}
.priorityMedium {
-fx-control-inner-background: #1d1d1d;
-fx-accent: derive(-fx-control-inner-background, -40%);
-fx-cell-hover-color: derive(-fx-control-inner-background, -20%);
}
try this its perfectly worked...
tablecol.setCellFactory(new Callback<TableColumn<CheckDo, String>, TableCell<CheckDo, String>>() {
#Override
public TableCell<CheckDo, String> call(TableColumn<CheckDo, String> p) {
return new TableCell<CheckDo, String>() {
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!isEmpty())
this.setStyle("-fx-background-color:red");
this.getTableRow().setStyle("-fx-background-color:red");
setText(item);
}
}
};

Resources