Javafx select multiple rows
Asked Answered
B

3

19

I'm trying to select multiple rows in JavaFX but I don't want to use keyboard (i.e. SHIFT key) for that. It should be selected after I click on it and when I click on another column it should be selected as well.

I checked some other answers here but I couldn't 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);
Both answered 22/3, 2014 at 19:49 Comment(2)
I would add a multi-select button like android. Click the button the subsequent selections get added (or maybe removed after another click) to a list of selections.Cutaneous
could you give a code example maybe in javafx?Both
G
44
tableView.getSelectionModel().setSelectionMode(
    SelectionMode.MULTIPLE
);
Grenade answered 22/3, 2014 at 20:30 Comment(5)
i tried that but it doesnt work..i added after boxTable.setItems(boxData); in my code ..do i do it wrong or ?Both
You have two tables in hour code (tableView and boxTable), that doesn't look right, so you have other issues than multiple selection.Grenade
that was writing mistake..it doesnt make any problem i corrected itBoth
Please correct all problems so that somebody could run your code. Currently boxTable.setItems would give a NullPointerException because you never create a boxTable.Grenade
@Grenade , after doing what u suggested we still need to select multiple rows with keyboard (Ctrl+Click), is there a way do it with only mouse click?Lichter
M
5

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;
    }
});
Menadione answered 25/8, 2017 at 11:6 Comment(0)
C
4

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);
        }
    }

}
Cutaneous answered 22/3, 2014 at 23:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.