JavaFX onMouseClickedEvent on ImageView - javafx

I have an ImageView with an Image inside it and when the image is clicked, a MouseClicked event should be triggered. However, the application is not even printing the test line.
Image cancel = new Image("/cancel.svg.png", 15, 15, false, false);
ImageView view = new ImageView(cancel);
view.setPickOnBounds(true);
view.setOnMouseClicked(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent event) {
System.out.println("hi");
/** execute code **/
}
});
Complete version:
I have a ListView called "found_tags_list" and every cell inside that ListView should be a new class called: "ButtonListCell". I did this to add extra content to the cells based on some statements.
found_tags_list.setCellFactory(new Callback<ListView<String>, ListCell>() {
#Override
public ListCell call(ListView<String> param) {
return new ButtonListCell();
}
});
Entire Cell class:
class ButtonListCell extends ListCell<String> {
#Override
public void updateItem(String obj, boolean empty) {
super.updateItem(obj, empty);
if (obj == null || obj.isEmpty() || empty) {
setText(null);
setGraphic(null);
} else {
setText(obj);
if (valid_tags.indexOf(obj) >= 0) {
setTextFill(Color.GREEN);
setGraphic(null);
} else {
Image cancel = new Image("/cancel.png", 15, 15, false, false);
ImageView view = new ImageView(cancel);
view.setPickOnBounds(true);
view.setOnMouseClicked(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent event) {
System.out.println("hi");
String item = getItem();
found_tags_list.getItems().remove(item);
for (Tag tag : rfidset) {
if (tag.getId().equals(item)) {
rfidset.remove(tag);
return;
}
}
}
});
setGraphic(view);
setTextFill(Color.RED);
setContentDisplay(ContentDisplay.RIGHT);
}
}
}

Related

JavaFX add/remove button in TableView cell based on row value

This code has a TavbleView in it, the final column has buttons to act on the column, view & clear. the clear button should only be present or enabled (either would be fine) if the given row is in a known state. Here is the code to always display both buttons, it is coded right now that when the "canClear" property is false, no action is taken:
private void addActionsToTable() {
TableColumn<searchResults, Void> actionColumn = new TableColumn("Action");
actionColumn.setCellFactory(col -> new TableCell<searchResults, Void>() {
private final HBox container;
{
Button viewBtn = new Button("View");
Button clearBtn = new Button("Clear");
viewBtn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
searchResults data = getTableView().getItems().get(getIndex());
gotoView(data.getLogNo());
}
});
clearBtn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
searchResults data = getTableView().getItems().get(getIndex());
String logNo = data.getLogNo();
String serialNumber = data.getSerial();
Boolean canClear = data.getCanClear();
if(canClear)
{
// Take action that has been cut for simplicity
}
}
});
container = new HBox(5, viewBtn, clearBtn);
}
#Override
public void updateItem(Void item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
setGraphic(container);
}
}
});
SearchTable.getColumns().add(actionColumn);
actionColumn.setPrefWidth(175);
}
What need to happen so that the Clear button is either disabled or not displayed when data.getCanClear() is false?
Assuming your searchResults (sic) class has a BooleanProperty canClearProperty() method:
actionColumn.setCellFactory(col -> new TableCell<searchResults, Void>() {
private final HBox container;
private final Button clearButton ;
{
Button viewBtn = new Button("View");
clearBtn = new Button("Clear");
viewBtn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
searchResults data = getTableView().getItems().get(getIndex());
gotoView(data.getLogNo());
}
});
clearBtn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
searchResults data = getTableView().getItems().get(getIndex());
String logNo = data.getLogNo();
String serialNumber = data.getSerial();
Boolean canClear = data.getCanClear();
if(canClear)
{
// Take action that has been cut for simplicity
}
}
});
container = new HBox(5, viewBtn, clearBtn);
}
#Override
public void updateItem(Void item, boolean empty) {
clearButton.disableProperty().unbind();
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
clearButton.disableProperty().bind(
getTableView().getItems().get(getIndex())
.canClearProperty().not());
setGraphic(container);
}
}
});

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?

Graphic on TreeItem dissapears on drag and drop

I have this basic code which adds drag and drop functionality to tree views.
The code works just fine, but when one treeitem is dragged, dropped and added over to another treeitem, the graphic on the treeitem in the original treecell dissapears, while the graphic follows the dragged element and is visible in the new treeitem.
See the image for example, the treeitem "Name" has been dragged over to "Column Name" and lost it's graphic. Alltough the new TreeItem under "Column Name" still has it graphics.
The code for adding drag and drop is this:
private void addDragAndDrop(TreeCell<String> treeCell, MainFXMLController mainFXMLController) {
treeCell.setOnDragDetected(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println("setOnDragDetected");
Dragboard db = treeCell.startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
content.putString(event.toString());
db.setContent(content);
DRAGGEDSOURCE = treeCell;
DRAGGEDINDEX = (treeCell.getTreeView().getSelectionModel().getSelectedIndex());
}
});
treeCell.setOnDragOver(new EventHandler<DragEvent>() {
//brukeren har dragget det over et element
public void handle(DragEvent event) {
DRAGGEDTARGET = treeCell.getTreeItem();
if (event.getGestureSource() != treeCell
&& event.getDragboard().hasString()) {
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}
}
});
treeCell.setOnDragDropped(new EventHandler<DragEvent>() {
public void handle(DragEvent event) {
DRAGGEDTARGET.getChildren().add(DRAGGEDSOURCE.getTreeItem());
}
);
}
public void makeTreeViewDragAble(TreeView treeView, MainFXMLController mainFXMLController) {
treeView.setCellFactory(new Callback<TreeView<String>, TreeCell<String>>() {
#Override
public TreeCell<String> call(TreeView<String> stringTreeView) {
TreeCell<String> treeCell = new TreeCell<String>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty && item != null) {
setText(item);
setGraphic(getTreeItem().getGraphic());
} else {
setText(null);
setGraphic(null);
}
}
};
addDragAndDrop(treeCell, mainFXMLController);
treeView.setEditable(true);
return treeCell;
}
});
}
As #James_D and I have concluded on, this is because I am trying to have two instances of the imageView. The solution is to set a new image view on the old item.

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

setOnMouseEntered and setOnMouseExited foreverloop

I use a PopOver from controlsfx to display detail-data from a TableCell. I use a tableCellFactory to create individual PopOvers. I have a problem with this code:
public class PopupTableCell extends TableCell {
#Override
protected void updateItem(final Object item, boolean empty) {
super.updateItem(item, empty);
if (empty){
setText(null);
} //if
else {
setText(item.toString());
// PopUp Anzeigen.
final PopOver PopUp = new PopOver();
PopUp.setContentNode(new Label(item.toString()));
setOnMouseEntered(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
Point MouseLocation = MouseInfo.getPointerInfo().getLocation();
PopUp.show(PopupTableCell.this, MouseLocation.getX(), MouseLocation.getY());
System.out.println("entered");
}
});
setOnMouseExited(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
System.out.println("exited");
PopUp.hide();
}
});
}
}
When I place the cursor over a cell, it begins firing the entered and the exited events forever (even with a non moving mouse cursor.
How can I achieve the wanted behavior:
Mouse inside table cell -> popover.show()
Mouse leaves table cell -> popover.hide()
This is how I solved the same problem for me.
owner.setOnMouseMoved(evt -> {
if (owner.getLayoutBounds().contains(evt.getX(), evt.getY())) {
if (!popOver.isShowing()) {
popOver.show(owner);
}
}
});
owner.setOnMouseExited(evt -> {
if (owner.getLayoutBounds().contains(evt.getX(), evt.getY())) {
if (!popOver.isShowing())
popOver.show(owner);
} else {
popOver.hide();
}
});

Resources