remove cell from comboBox on click javafx - java

I have the following action when clicking on a cell of a Combobox in javafx.
Now i want the cell to be removed from the Combobox when it was clicked. How can I do that? Is there any way to remove a cell?
notificationCombo.setCellFactory(lv -> {
ListCell<String> cell = new ListCell<String>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setText(empty ? null : item);
}
};
cell.setOnMousePressed(e -> {
if (! cell.isEmpty()) {
for(Product product:products){
if(cell.getText().equals(product.getName())){
selectedLoadProduct = product;
loadProduct(selectedLoadProduct);
updateProd(selectedLoadProduct,false);
initGui();
selectedLoadProduct = null;
createProductSelection();
}}}
});
return cell ;
});

Related

Listview setCellFactory with generic label

I try do create a customize item within ListView, let's say it's label and I want to execute setCellFactory, while I'm using Label I don't see the item (the text of the label), why?
ListView<Label> list = new ListView<Label>();
ObservableList<Label> data = FXCollections.observableArrayList(
new Label("123"), new Label("45678999"));
#Override
public void start(Stage stage) {
VBox box = new VBox();
Scene scene = new Scene(box, 200, 200);
stage.setScene(scene);
stage.setTitle("ListViewExample");
box.getChildren().addAll(list);
VBox.setVgrow(list, Priority.ALWAYS);
list.setItems(data);
list.setCellFactory(new Callback<ListView<Label>, ListCell<Label>>() {
#Override
public ListCell<Label> call(ListView<Label> list) {
ListCell<Label> cell = new ListCell<Label>() {
#Override
public void updateItem(Label item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
setItem(item);
}
}
};
return cell;
}
}
);
stage.show();
}
If you do want to show items extending Node there is no need to use custom ListCells. The ListCells of the default factory are doing this already.
However in your case you're calling setItem instead of setGraphic and also you do not set the property back to null, when the cell becomes empty:
list.setCellFactory(new Callback<ListView<Label>, ListCell<Label>>() {
#Override
public ListCell<Label> call(ListView<Label> list) {
ListCell<Label> cell = new ListCell<Label>() {
#Override
public void updateItem(Label item, boolean empty) {
super.updateItem(item, empty);
// also sets to graphic to null when the cell becomes empty
setGraphic(item);
}
};
return cell;
}
});

How do i set a cell value in javafx tablecell after a drag and drop event is complete?

I'm designing an application that allows a drag and drop on TableView cells.
However, once the drag and drop is complete and the values of the cells switched successfully, a double-click on the cells where drag and drop has been effected makes the cells change back to their original text before drag and drop.
Help me solve this issue. The following code is used to set cellFactoryValue for all the cells. I am new to javafx.
private void setCellFactoryForColumns(TableColumn<TimeTable, String> col)
{
col.setCellFactory((TableColumn<TimeTable, String> e) -> {
TableCell<TimeTable, String> cell = new TableCell<TimeTable, String>() {
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
setGraphic(null);
} else {
setText(item);
setGraphic(null);
}
}
};
col.setOnEditCommit((CellEditEvent<TimeTable, String> t) -> {
((TimeTable)t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setDay(t.getNewValue());
});
cell.setOnDragDetected((MouseEvent event) -> {
Dragboard db = cell.startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
content.putString(cell.getText());
db.setContent(content);
cell.setStyle("-fx-background-color: red;"
+ "-fx-text-fill: white;");
cell.startEdit();
cell.setText("Dragged");
event.consume();
});
cell.setOnDragOver((DragEvent event) ->{
if(event.getGestureSource() != cell &&
event.getDragboard().hasString())
{
event.acceptTransferModes(TransferMode.MOVE);
cell.setStyle("-fx-background-color: green;"
+ "-fx-text-fill: white;");
}
event.consume();
});
cell.setOnDragEntered((DragEvent event) ->{
if(event.getGestureSource() != cell &&
event.getDragboard().hasString()){
cell.setStyle("-fx-background-color: yellow;");
}
event.consume();
});
cell.setOnDragExited((DragEvent event) -> {
cell.setStyle("-fx-background-color: grey;");
event.consume();
});
cell.setOnDragDropped((DragEvent event) -> {
Dragboard db = event.getDragboard();
boolean success = false;
if(db.hasString())
{
holdData = cell.getText();
cell.setText(db.getString());
success = true;
}
event.setDropCompleted(success);
event.consume();
});
cell.setOnDragDone((DragEvent event) ->{
if(event.getTransferMode() == TransferMode.MOVE)
{
cell.setText(holdData);
}
event.consume();
});
return cell;
});
}
You just change the text in the cell, not the property of the item. Therefore every time a new item is assigned to the TableCell, the old value is used as text.
This also happens, if you scroll the cell containing a item out of view.
To fix this replace the
cell.setText(db.getString());
and
cell.setText(holdData);
statements in the onDragDone/onDragDropped handlers with
update(cell, db.getString());
and
update(cell, holdData);
respectively and implement the update method like this:
static void update(TableCell<TimeTable, String> cell, String newValue) {
((TableRow<TimeTable>)cell.getTableRow()).getItem().setDay(newValue);
// the below line would be needed, if the setter does not trigger
// a update of the ObservableValue returned by the cellValueFactory
// cell.getTableView().refresh();
}
In case your cellValueFactory returns a WritableProperty that allows writing to the item, the method can be written more general as
static <I,P>void update(TableCell<I, P> cell, P newValue) {
WritableValue<P> property = (WritableValue<P>) cell.getTableColumn().getCellObservableValue(((TableRow<I>)cell.getTableRow()).getItem());
property.setValue(newValue);
}

Scroll to manipulate the TableView, erases the contents of the TextField created in table

I put the numbers in my textfields located in Mirror column, But when I handle the scroll bar (scroll my table), the contents of the textfields are deleted. Is there any solution to this problem?
The code that creates my table:
#SuppressWarnings({ "unchecked", "rawtypes" })
private void loadTabMirror() {
TableColumn request = new TableColumn("Pedido");
request.setCellValueFactory(new PropertyValueFactory<MirrorVo, String>("request"));
request.setMinWidth(150);
TableColumn applicant = new TableColumn("Requerente");
applicant.setCellValueFactory(new PropertyValueFactory<MirrorVo, String>("name"));
applicant.setMinWidth(400);
TableColumn numberRg = new TableColumn("N° RG");
numberRg.setCellValueFactory(new PropertyValueFactory<MirrorVo, String>("rg"));
numberRg.setMinWidth(80);
Callback<TableColumn<MirrorVo, String>, TableCell<MirrorVo, String>> txtMirrorCallBack =
new Callback<TableColumn<MirrorVo, String>, TableCell<MirrorVo, String>>() {
#Override
public TableCell call(final TableColumn param) {
final TableCell cell = new TableCell() {
#Override
public void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else if(item == null){
TextField textField = loadRuleTextField(param,getIndex());
textFieldMirrors.add(textField);
setGraphic(textField);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
}
};
return cell;
}
};
TableColumn mirror = new TableColumn("Espelho");
mirror.setCellValueFactory(new PropertyValueFactory<MirrorVo, Integer>("mirror"));
mirror.setMinWidth(100);
mirror.setCellFactory(txtMirrorCallBack);
Callback<TableColumn<MirrorVo, String>, TableCell<MirrorVo, String>> imgMirrorInfo =
new Callback<TableColumn<MirrorVo, String>, TableCell<MirrorVo, String>>() {
#Override
public TableCell<MirrorVo, String> call(
TableColumn<MirrorVo, String> param) {
final TableCell cell = new TableCell() {
#Override
public void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
ImageView imgViewInfo = new ImageView(new Image("resources/img/info.png"));
imgViewInfo.setFitWidth(32);
imgViewInfo.setFitHeight(32);
imgViewInfo.setVisible(false);
imgViewInfos.put(getIndex(), imgViewInfo);
setGraphic(imgViewInfo);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
}
};
return cell;
}
};
TableColumn info = new TableColumn("Status");
info.setMinWidth(40);
info.setCellFactory(imgMirrorInfo);
Callback<TableColumn<CivilRecord, String>, TableCell<CivilRecord, String>> btnInvalidateCallBack = addActionBtnInvalidate();
TableColumn validation = new TableColumn(" ");
validation.setCellValueFactory(new PropertyValueFactory<CivilRecord, String>("dateRegisterLot"));
validation.setMinWidth(100);
validation.setCellFactory(btnInvalidateCallBack);
Callback<TableColumn<CivilRecord, String>, TableCell<CivilRecord, String>> btnAutoGenerateCallBack = addActionBtnAutoGenerate();
TableColumn autoGenerate = new TableColumn(" ");
autoGenerate.setCellValueFactory(new PropertyValueFactory<CivilRecord, String>("dateRegisterLot"));
autoGenerate.setMinWidth(100);
autoGenerate.setCellFactory(btnAutoGenerateCallBack);
tabMirror.getColumns().addAll(request,applicant,numberRg,mirror,info,autoGenerate, validation);
}
Your TableCell for the mirror column never actually handles the case where the item has content (i.e. the item is not null).
As you scroll, what probably happens is that TableCells which are scrolled off the visible portion of the screen get updated as empty cells, then they get reused at some point for new items that are displayed. So the updateItem() method is first called with empty=true (setting the text and graphic to null), and is later called with empty=false and item as the item to be displayed. Since your updateItem method doesn't handle this case at all, the cell's text and graphic remain null.
You need to change the updateItem method so that it handles all possible cases:
empty == true (you already have)
empty == false && item == null (you already have)
empty == false && item != null (you do not handle)

JavaFX TableColumn text wrapping

I am experiencing an issue when resizing a TableView which contains text items that wrap around TableCell items. Upon resizing, hidden values are resized but the visible items do not re-calculate the text wrapping.
The tweets in the red box were hidden during the resize and had their text wrapping adjusted as expected. Tweets above the box were visible during the resize phase and still have the old wrapping.
Below is my code for the resize phase.
fxSearchResultsTableTweet.setCellFactory(new Callback<TableColumn<Status, String>, TableCell<Status, String>>() {
#Override
public TableCell<Status, String> call(TableColumn<Status, String> arg0) {
return new TableCell<Status, String>() {
private Text text;
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!isEmpty()) {
text = new Text(item.toString());
text.setWrappingWidth(fxSearchResultsTableTweet.getWidth());
this.setWrapText(true);
setGraphic(text);
}
}
};
}
});
}
Any help would be greatly appreciated.
This is closer, but not great:
textCol.setCellFactory(new Callback<TableColumn<Status, String>, TableCell<String, String>>() {
#Override
public TableCell<Status, String> call(
TableColumn<Status, String> param) {
TableCell<Status, String> cell = new TableCell<>();
Text text = new Text();
cell.setGraphic(text);
cell.setPrefHeight(Control.USE_COMPUTED_SIZE);
text.wrappingWidthProperty().bind(cell.widthProperty());
text.textProperty().bind(cell.itemProperty());
return cell ;
}
});
In 2.2 this displays the wrong height when you add new items to the table, then on resize the cells are sized correctly. In 8 it's almost perfect, just seems to fail after the first item is added (at least in my mock-up).
As noted in the comments,
textCol.setCellFactory(tc -> {
TableCell<Status, String> cell = new TableCell<>();
Text text = new Text();
cell.setGraphic(text);
cell.setPrefHeight(Control.USE_COMPUTED_SIZE);
text.wrappingWidthProperty().bind(textCol.widthProperty());
text.textProperty().bind(cell.itemProperty());
return cell ;
});
appears to work better.
Just add cell factory on each table of column.
It should add before adding your data to table view.
It is worked fine for me.
yourTableColumn.setCellFactory(param -> {
return new TableCell<YourDataClass, String>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
setStyle("");
} else {
Text text = new Text(item);
text.setStyle("-fx-text-alignment:justify;");
text.wrappingWidthProperty().bind(getTableColumn().widthProperty().subtract(35));
setGraphic(text);
}
}
};
});

Context Menu visibility in TableView JavaFX

I am creating TableView in JavaFX. In which I want to show Context Menu in right click of mouse in tableView. So I am adding an EventHandler on table as given below :
TableView tableView=new TableView();
EventHandler event = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent me) {
if (me.getButton() == MouseButton.SECONDARY) {
tableView.getContextMenu().show(tableView, me.getSceneX(), me.getSceneY());
}
}
};
tableView.addEventHandler(MouseEvent.MOUSE_CLICKED, event);
But my problem is that Context Menu is visible wherever I right click on any part of table.
I want to do that Context Menu should be only visible if I clicked on any rows in TableView.
i.e. How would I get row number in TableView at specific point, So that my Context Menu should be only visible, if I clicked on any row of TableView.
The best solution I found was to check if the y coordinate is outside of the bounds of the column header and then to explicitly show the menu.
ContextMenu visibleMenu = null;
tableView.setOnMouseClicked((MouseEvent e) -> {
if (visibleMenu !=null) {
visibleMenu.hide();
visibleMenu = null;
}
if (e.getButton()==MouseButton.SECONDARY) {
double columnHeaderHeight = tableView.lookup(".column-header-background").getBoundsInLocal().getHeight();
if (e.getY()>columnHeaderHeight) {
visibleMenu = getContextMenu(); // build on the fly or use a prebuild menu
visibleMenu.show(tableView, e.getScreenX(), e.getScreenY());
} else {
// you could show a header specific context menu here
}
}
});
The added benefit is that you can build the context menu on the fly with context sensitive items (that for example only appear if a certain type of cell is selected), or just reuse a prebuild contextmenu as setContextMenu does, up to you.
Add context menu to the specific cells using CellFactory not to the whole table.
E.g. using Table from Oracle tutorial:
TableColumn firstNameCol = new TableColumn();
firstNameCol.setText("First");
firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName"));
firstNameCol.setCellFactory(new Callback<TableColumn, TableCell>() {
#Override
public TableCell call(final TableColumn param) {
final TableCell cell = new TableCell() {
#Override
public void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
} else {
if (isEditing()) {
setText(null);
} else {
setText(getItem().toString());
setGraphic(null);
}
}
}
};
// This way I will have context menu only for specific column
cell.setContextMenu(ContextMenuBuilder.create().items(MenuItemBuilder.create().text("menu").build()).build());
return cell;
}
});
may be the older question. There is a solution, like getting the target of the mouse event of the table and check for instance for class TableCellSkin and display the context menu as,
table.addEventHandler(MouseEvent.MOUSE_CLICKED,
new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent e) {
if (e.getButton() == MouseButton.SECONDARY
&& !isRowEmpty) {
EventTarget target = e.getTarget();
if (target instanceof TableCellSkin
|| ((Node) target).getParent() instanceof TableCellSkin) {
// do your stuff. Context menu will be displayed by default
} else {
// hide the context menu when click event is outside table row
table.getContextMenu().hide();
}
}
}
});
#FXML
void tableContextMenuRequested(ContextMenuEvent event) {
if (tableview.getSelectionModel().getSelectedItems().size() == 0) {
tableContextMenu.hide();
}
}

Categories

Resources