I m trying to select multiple rows in javafx but i dont want to use keyboard (SHIFT)for that.it should be after i click on it selected and when i click on an other column it should be selected as well.
I check some other answers here but i couldnt find something short and handy.Is there a shorter way to do it ?
@FXML
private static Logger logger = Logger.getLogger(MainFrameControl.class);
public TableView<Box> boxTable;
protected final ObservableList<Box> boxData = FXCollections.observableArrayList();
Service service = new ServiceImpl();
private Stage mainStage;
public MainFrameControl(Stage mainStage) {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("MainFrame.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
this.mainStage = mainStage;
Stage stage = new Stage();
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
ArrayList<Box> list = service.findAllBoxen();
TableColumn<Box, String> boxnameColumn = (TableColumn<Box, String>) boxTable.getColumns().get(0);
boxnameColumn.setCellValueFactory(new PropertyValueFactory<Box, String>("boxName"));
TableColumn<Box, String> sizeColumn = (TableColumn<Box, String>) boxTable.getColumns().get(1);
sizeColumn.setCellValueFactory(new PropertyValueFactory<Box, String>("size"));
TableColumn<Box, String> windowColumn = (TableColumn<Box, String>) boxTable.getColumns().get(2);
windowColumn.setCellValueFactory(new PropertyValueFactory<Box, String>("window"));
TableColumn<Box, String> costColumn = (TableColumn<Box, String>) boxTable.getColumns().get(3);
costColumn.setCellValueFactory(new PropertyValueFactory<Box, String>("cost"));
TableColumn<Box, String> locationColumn = (TableColumn<Box, String>) boxTable.getColumns().get(4);
locationColumn.setCellValueFactory(new PropertyValueFactory<Box, String>("location"));
TableColumn<Box, Boolean> beddingColumn = (TableColumn<Box, Boolean>) boxTable.getColumns().get(5);
beddingColumn.setCellValueFactory(new PropertyValueFactory<Box, Boolean>("bedding"));
boxTable.setItems(boxData);
tableView.getSelectionModel().setSelectionMode(
SelectionMode.MULTIPLE
);
This is just a basic idea of what you may be looking for. Could use a bit of improvement but I'm unclear on the intended use.
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TablePosition;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TableTest extends Application {
@Override
public void start(Stage primaryStage) {
ObservableList<LineItem> items = FXCollections.observableArrayList();
items.addAll(new LineItem("hello",123.45),
new LineItem("paid in full",0.01),
new LineItem("paid",0.01),
new LineItem("due",0.01),
new LineItem("paid",0.01));
ObservableList<LineItem> filteredItems = FXCollections.observableArrayList(items);
TableView<LineItem> tableView = new TableView<>(filteredItems);
ObservableList<TablePosition> selectedCells = FXCollections.observableArrayList();
Button multi = new Button("Multi-select");
multi.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
multi.setText((multi.getText().equals("Multi-select"))?"Single-select":"Multi-select");
selectedCells.clear();
}
});
TableColumn<LineItem,String> descCol = new TableColumn<>("desc");
descCol.setCellValueFactory(new PropertyValueFactory<>("desc"));
TableColumn<LineItem, Double> amountCol = new TableColumn<>("amount");
amountCol.setCellValueFactory(new PropertyValueFactory<>("amount"));
tableView.getColumns().addAll(descCol,amountCol);
tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
tableView.getSelectionModel().setCellSelectionEnabled(true);
//maybe you want onTouchPressed here for tablet
tableView.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (multi.getText().equals("Single-select")) return;
selectedCells.add(
tableView.getSelectionModel().getSelectedCells().get(
tableView.getSelectionModel().getSelectedCells().size()-1
)
);
for (TablePosition tp : selectedCells){
tableView.getSelectionModel().select(tp.getRow(), tp.getTableColumn());
}
}
});
VBox root = new VBox();
root.getChildren().addAll(tableView, multi);
Scene scene = new Scene(root, 300, 300);
primaryStage.setTitle("multi select table test");
primaryStage.setScene(scene);
primaryStage.show();
}
public class LineItem {
private final StringProperty desc = new SimpleStringProperty();
private final DoubleProperty amount = new SimpleDoubleProperty();
public StringProperty descProperty() {return desc;}
public DoubleProperty amountProperty() {return amount;}
public LineItem(String dsc, double amt) {
desc.set(dsc); amount.set(amt);
}
}
}
A custom RowFactory is a good solution for this problem:
boxTable.setRowFactory(new Callback<TableView<Box>, TableRow<Box>>() {
@Override
public TableRow<Box> call(TableView<Box> tableView2)
{
final TableRow<Box> row = new TableRow<>();
row.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event)
{
final int index = row.getIndex();
if (index >= 0 && index < boxTable.getItems().size())
{
if(boxTable.getSelectionModel().isSelected(index))
boxTable.getSelectionModel().clearSelection(index);
else
boxTable.getSelectionModel().select(index);
event.consume();
}
}
});
return row;
}
});