here is my code
// this event is attached to TableCell
public EventHandler dblclickDescription = new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent event) {
if(event.getButton().equals(MouseButton.PRIMARY)){
if(event.getClickCount() == 2){
printRow(event.getTarget());
}
}
event.consume();
}
};
// print row
public void printRow(Object o){
Text text = (Text) o;
// ??? don't know what to write here
System.out.println(row.toString());
}
1) how do I get from the cell I clicked to the row?
2) can I attach the event to the whole row instead of each column?
EDIT:
3) I thought that I attached the event on TableCell
TableCell cell = TableColumn.DEFAULT_CELL_FACTORY.call(p);
cell.setOnMouseClicked(dblclickDescription);
but when I tested,
event.getSource();// is a TableColumn
event.getTarget();// is a Text if clicked on text
event.getTarget();// is a TableColumn if clicked on empty space, even if that cell has text
is there a way to get TableCell from MouseEvent?
To answer your specific questions:
how do I get from the cell I clicked to the row?
TableCell defines a getTableRow() method, returning the TableRow. So you can do
Object item = cell.getTableRow().getItem();
which will give you the row item from the table (i.e. the correct element of table.getItems()). You can also get this from table.getItems().get(cell.getIndex()) if you prefer.
can I attach the event to the whole row instead of each column?
Yes. Define a rowFactory:
TableView<MyDataType> table = new TableView<>();
table.setRowFactory(tv -> {
TableRow<MyDataType> row = new TableRow<>();
row.setOnMouseClicked(event -> {
if (! row.isEmpty() && event.getButton()==MouseButton.PRIMARY
&& event.getClickCount() == 2) {
MyDataType clickedRow = row.getItem();
printRow(clickedRow);
}
});
return row ;
});
// ...
private void printRow(MyDataType item) {
// ...
}
To get back the index of the row or the selected item, use this code :
Object object = table.getSelectionModel().selectedItemProperty().get();
int index = table.getSelectionModel().selectedIndexProperty().get();
Then you can add a listener when the index / object change like this :
table.getSelectionModel().selectedIndexProperty().addListener((num) -> function());
Related
I have JavaFX tableview that I have created dynamically. When one double-clicks on a cell on the tableview, I need to get the name of the column the cell is in and the value of the first cell in the row this cell is in. I have tried searching over google and found no particular solution to this problem. Kindly show me some sample code.
Ok, so first, let's assume your TableView is attached to a model:
public TableView<MyModel> myTable;
where MyModel is something like:
public class MyModel {
private Integer id;
private String name;
// ... etc.
}
so, MyModel is a common POJO. You can have columns of your TableView like:
TableColumn<MyModel, Integer> id = new TableColumn<>("ID");
id.setCellValueFactory(new PropertyValueFactory<>("id"));
TableColumn<MyModel, String> name = new TableColumn<>("Name");
name.setCellValueFactory(new PropertyValueFactory<>("name"));
and then, to add the columns to your table:
myTable.getColumns().addAll(id, name);
Now, let's listen to the click event using a rowFactory:
myTable.setRowFactory(tv -> {
TableRow<MyModel> row = new TableRow<>();
row.setOnMouseClicked(event -> {
// check for non-empty rows, double-click with the primary button of the mouse
if (!row.isEmpty() && event.getClickCount() == 2 && event.getButton() == MouseButton.PRIMARY) {
MyModel element = row.getItem();
// now you can do whatever you want with the myModel variable.
System.out.println(element);
}
});
return row ;
});
That should do the work.
I have customized a Hyperlink cell here. I want the tableview to select the content when I click this link, but after I add Hyperlink, the tableview's selected seems to be invalid.
tb_uGoodUrl.setCellFactory(new Callback<TableColumn<GoodModel, String>, TableCell<GoodModel, String>>() {
#Override
public TableCell<GoodModel, String> call(TableColumn<GoodModel, String> param) {
TableCell<GoodModel, String> cell = new TableCell<GoodModel, String>() {
private final Hyperlink hyperlink = new Hyperlink();
{
hyperlink.setOnMouseClicked(event -> {
if(event.getClickCount() == 2){
String url = getItem();
hostServices.showDocument(url);
}
});
}
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
}else {
hyperlink.setText(getItem());
setGraphic(hyperlink);
}
}
};
return cell;
}
});
Click on the link, the cell is not selected
If the cell is not selected, a null exception will be reported when the following code is used.
TablePosition pos = tableView.getSelectionModel().getSelectedCells().get(0);
int row = pos.getRow();
// Item here is the table view type:
GoodModel item = tableView.getItems().get(row);
TableColumn col = pos.getTableColumn();
// this gives the value in the selected cell:
String data = (String) col.getCellObservableValue(item).getValue();
The effect you want to achieve is as follows
Rendering
You can manually select the cell, using the table's selection model, when the Hyperlink is clicked on.
// Assuming this code is inside a TableCell implementation
hyperlink.setOnAction(event -> {
event.consume();
getTableView().getSelectionModel().select(getIndex(), getTableColumn());
// show your document
});
I used the onAction property which will be fired when the Hyperlink has been clicked once. This is typical behavior for a hyperlink, but if you want to only perform the action on a double-click then you can keep using your onMouseClicked handler.
Note the above does not take into account multiple-selection mode.
I have following problem in javafx tableview, my table view is connected to certain model, and normal CRUD operations work with no issues, I also added a column which is not connected to ANY data model, and it just contains a hyperlink on which user can click, and he is prompted with a pop up.
All of this work, what it does not work is, when I click on hyperlink I want to also pass the row value, and normally it works like
tableview.getSelectionModel().getSelectedItem();
But now it does not work, since i am not clicking directly a cell, but I click a hyperlink, and if I click first some row and then hyperlink, I get that row that I highlighted. Is there any way to select row when clicking hyperlink,so I don't have to first click row then hyperlink in same row.
public class RemoveCell<T> extends TableCell<T, Void> {
private final Hyperlink link;
private final Hyperlink link1;
private final HBox pane = new HBox();
public RemoveCell() {
link = new Hyperlink("Remove");
link1 = new Hyperlink("Edit");
pane.getChildren().addAll(link,link1);
link1.setOnAction(evt -> {
//lagerRet();
if(tableView.getSelectionModel().getSelectedItem()!=null) {
System.out.println("not null");
}
else {
System.out.println("null");
}
// remove row item from tableview
// ap.getChildren().removeAll();
//ap.getChildren().setAll(mcon.loadParent(FxmlView.CHART));
PopOver popsy = new PopOver();
try {
popsy.setContentNode(control.loadUni(FxmlView.POP));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//popsy.setContentNode(panemain);
popsy.headerAlwaysVisibleProperty().set(true);;
popsy.show(link);
});
link.setOnAction(evt -> {
// remove row item from tableview
System.out.println("a quick test");
});
}
#Override
protected void updateItem(Void item, boolean empty) {
super.updateItem(item, empty);
setGraphic(empty ? null : pane );
//setGraphic(empty ? null : link1 );
}
}
and lastly this how I populate column
testColumn.setCellFactory(tc -> new RemoveCell<>());
It's possible to access the row item via TableRow containing the TableCell.
T item = getTableRow().getItem();
It's also possible to get the index in TableView.items using TableCell.getIndex which allows for removal without searching for the item in the list first.
int itemIndex = getIndex();
getTableView().getItems().remove(itemIndex);
I need to click on the button that is already in a column to automatically select the row to be able to get and set the selected item. Otherwise, generate nullpointer. I was thinking of adding a listener that when I click the button select the row directly, but I do not know.
ScreenShot :
This is the code:
botonVisitar.setOnAction((ActionEvent event) -> {
TextInputDialog dialog1 = new TextInputDialog();
Stage stage1 = (Stage) dialog1.getDialogPane().getScene().getWindow();
stage1.getIcons().add(new Image(this.getClass().getResource("icono.jpg").toString()));
dialog1.setTitle("Visita:");
dialog1.setContentText("Ingresar Tipo de visita: (por ejemplo: llamada, mail, mensaje, etc)");
Optional<String> result1 = dialog1.showAndWait();
if (result1.isPresent()) {
TablaVisita.getSelectionModel().getSelectedItem().setTipoVisita(result1.get());
TablaVisita.getSelectionModel().getSelectedItem().setFechaVisita(LocalDate.now());
//If it is not selected i get nullPointer.
}
I assume you're doing this in a custom TableCell used with a cellFactory, which means you can use the TableRow to get the table item:
new TableCell<MyItem, Void>() {
private final Button botonVisitar = new Button("Visitar");
{
botonVisitar.setOnAction((ActionEvent event) -> {
...
if (result1.isPresent()) {
MyItem item = (MyItem) getTableRow().getItem();
item.setTipoVisita(result1.get());
item.setFechaVisita(LocalDate.now());
}
});
}
#Override
public void updateItem(Void item, boolean empty) {
super.updateItem(item, empty);
setGraphic(empty ? null : botonVisitar);
}
}
I have a TableView, where I need to enable the selection of any cells(one at a time). For now, I use this code:
tableView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
#Override
public void changed(ObservableValue observableValue, Object oldValue, Object newValue) {
if(tableView.getSelectionModel().getSelectedItem() != null)
{
TableView.TableViewSelectionModel selectionModel = tableView.getSelectionModel();
ObservableList selectedCells = selectionModel.getSelectedCells();
TablePosition tablePosition = (TablePosition) selectedCells.get(0);
String val = (String)tablePosition.getTableColumn().getCellData(newValue);
System.out.println("Selected Value: " + val);
selectionTextField.appendText(val);
}
}
});
The problem is, I can't get the values of different cells in the same row after each other. I think it's because it's the same row, the selection listener is not triggered. I tried clearSelection(), but then I get out of bounds exception, and I read somewhere that I cant change the table model in the same listener. Any tips?
Thank you.
If you are using cell selection instead of row selection (in other words, if you have called tableView.getSelectionMode().setCellSelectionEnabled(true);), then you should observe the list of selected cells instead of the selectedItem property. The selectedItem property only indicates the row that is selected, so it only changes if you select a new row.
ObservableList<TablePosition> selectedCells = table.getSelectionModel().getSelectedCells() ;
selectedCells.addListener((ListChangeListener.Change<? extends TablePosition> change) -> {
if (selectedCells.size() > 0) {
TablePosition selectedCell = selectedCells.get(0);
TableColumn column = selectedCell.getTableColumn();
int rowIndex = selectedCell.getRow();
Object data = column.getCellObservableValue(rowIndex).getValue();
}
});