├── .gitignore ├── docs ├── README.md └── output.png ├── pom.xml └── src └── main ├── java └── np │ └── com │ └── ngopal │ └── tableviewdataselection │ ├── Gender.java │ ├── Person.java │ ├── TableViewDataDemoController.java │ └── TableViewDataSelection.java └── resources └── fxml └── TableViewDataFXML.fxml /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Maven template 3 | target/ 4 | pom.xml.tag 5 | pom.xml.releaseBackup 6 | pom.xml.versionsBackup 7 | pom.xml.next 8 | release.properties 9 | dependency-reduced-pom.xml 10 | buildNumber.properties 11 | .mvn/timing.properties 12 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar 13 | .mvn/wrapper/maven-wrapper.jar 14 | target/ 15 | nb*.xml 16 | *.iml 17 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # JavaFX TableView Data Selection 2 | 3 | This project is for doing the selection based upon the columns and row and show the index data of it. 4 | 5 | ### Requirement 6 | - JavaFX 14 7 | 8 | ### Usage 9 | ```shell script 10 | mvn clean javafx:run 11 | ``` 12 | 13 | #### Output 14 | ![Table View Data Selection](output.png) 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /docs/output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/privatejava/javafx-tableview-data-selection/e6faff47e583249ce24c20917bacdca0ca35c682/docs/output.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | np.com.ngopal 7 | javafx-tableview-data-selection 8 | 1.0-SNAPSHOT 9 | jar 10 | 11 | javafx-tableview-data-selection 12 | 13 | 14 | 14 15 | 14 16 | UTF-8 17 | np.com.ngopal.tableviewdataselection.MainApp 18 | 19 | 20 | 21 | 22 | org.openjfx 23 | javafx-controls 24 | 14 25 | 26 | 27 | 28 | org.openjfx 29 | javafx-fxml 30 | 14 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | org.openjfx 39 | javafx-maven-plugin 40 | 0.0.4 41 | 42 | 14 43 | 14 44 | 14 45 | np.com.ngopal.tableviewdataselection.TableViewDataSelection 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/main/java/np/com/ngopal/tableviewdataselection/Gender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | package np.com.ngopal.tableviewdataselection; 6 | 7 | /** 8 | * 9 | * @author Narayan G. Maharjan 10 | */ 11 | public enum Gender { 12 | MALE, FEMALE, OTHER; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/np/com/ngopal/tableviewdataselection/Person.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | package np.com.ngopal.tableviewdataselection; 6 | 7 | import javafx.beans.property.*; 8 | 9 | /** 10 | * 11 | * @author Narayan G. Maharjan 12 | */ 13 | public class Person { 14 | private final IntegerProperty sn = new SimpleIntegerProperty(); 15 | 16 | private final StringProperty address = new SimpleStringProperty(); 17 | 18 | private final StringProperty name = new SimpleStringProperty(); 19 | 20 | private final StringProperty phone = new SimpleStringProperty(); 21 | 22 | private final ObjectProperty gender = new SimpleObjectProperty(Gender.OTHER); 23 | 24 | public int getSn() { 25 | return sn.get(); 26 | } 27 | 28 | public void setSn(int value) { 29 | sn.set(value); 30 | } 31 | 32 | public IntegerProperty snProperty() { 33 | return sn; 34 | } 35 | 36 | public Gender getGender() { 37 | return gender.get(); 38 | } 39 | 40 | public void setGender(Gender value) { 41 | gender.set(value); 42 | } 43 | 44 | public ObjectProperty genderProperty() { 45 | return gender; 46 | } 47 | 48 | public String getPhone() { 49 | return phone.get(); 50 | } 51 | 52 | public void setPhone(String value) { 53 | phone.set(value); 54 | } 55 | 56 | public StringProperty phoneProperty() { 57 | return phone; 58 | } 59 | 60 | public String getAddress() { 61 | return address.get(); 62 | } 63 | 64 | public void setAddress(String value) { 65 | address.set(value); 66 | } 67 | 68 | public StringProperty addressProperty() { 69 | return address; 70 | } 71 | 72 | public String getName() { 73 | return name.get(); 74 | } 75 | 76 | public void setName(String value) { 77 | name.set(value); 78 | } 79 | 80 | public StringProperty nameProperty() { 81 | return name; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/np/com/ngopal/tableviewdataselection/TableViewDataDemoController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | package np.com.ngopal.tableviewdataselection; 6 | 7 | import java.net.URL; 8 | import java.util.ResourceBundle; 9 | import javafx.beans.value.ChangeListener; 10 | import javafx.beans.value.ObservableValue; 11 | import javafx.collections.FXCollections; 12 | import javafx.collections.ListChangeListener; 13 | import javafx.collections.ListChangeListener.Change; 14 | import javafx.collections.ObservableList; 15 | import javafx.event.EventHandler; 16 | import javafx.fxml.FXML; 17 | import javafx.scene.control.*; 18 | import javafx.scene.control.cell.PropertyValueFactory; 19 | import javafx.scene.input.*; 20 | import javafx.util.Callback; 21 | import javafx.util.StringConverter; 22 | 23 | /** 24 | * FXML Controller class 25 | * 26 | * @author Narayan G. Maharjan 27 | */ 28 | public class TableViewDataDemoController { 29 | /** 30 | * For the data transformation 31 | */ 32 | public static DataFormat dataFormat = new DataFormat("mydata"); 33 | 34 | @FXML 35 | private ToggleGroup selectionGrp; 36 | 37 | @FXML 38 | private ComboBox> colSelect; 39 | 40 | @FXML 41 | private RadioButton cellRadio, rowRadio; 42 | 43 | @FXML 44 | private ResourceBundle resources; 45 | 46 | @FXML 47 | private URL location; 48 | 49 | @FXML 50 | private ListView listView; 51 | 52 | @FXML 53 | private TableColumn addressCol; 54 | 55 | @FXML 56 | private TableColumn genderCol; 57 | 58 | @FXML 59 | private TableColumn nameCol; 60 | 61 | @FXML 62 | private TableColumn phoneCol; 63 | 64 | @FXML 65 | private TableColumn snCol; 66 | 67 | @FXML 68 | private TableView tableView; 69 | 70 | ObservableList selectedIndexes = FXCollections.observableArrayList(); 71 | 72 | @FXML 73 | void initialize() { 74 | assert addressCol != null : "fx:id=\"addressCol\" was not injected: check your FXML file 'TableViewDataFXML.fxml'."; 75 | assert genderCol != null : "fx:id=\"genderCol\" was not injected: check your FXML file 'TableViewDataFXML.fxml'."; 76 | assert nameCol != null : "fx:id=\"nameCol\" was not injected: check your FXML file 'TableViewDataFXML.fxml'."; 77 | assert phoneCol != null : "fx:id=\"phoneCol\" was not injected: check your FXML file 'TableViewDataFXML.fxml'."; 78 | assert snCol != null : "fx:id=\"snCol\" was not injected: check your FXML file 'TableViewDataFXML.fxml'."; 79 | assert tableView != null : "fx:id=\"tableView\" was not injected: check your FXML file 'TableViewDataFXML.fxml'."; 80 | 81 | // changed to multiple selection mode 82 | tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); 83 | // set cell value factories 84 | setCellValueFactories(); 85 | 86 | //set Dummy Data for the TableView 87 | tableView.setItems(getData()); 88 | 89 | //ListView items bound with selection index property of tableview 90 | listView.setItems(selectedIndexes); 91 | 92 | //change listview observable list 93 | tableView.getSelectionModel().getSelectedIndices().addListener(new ListChangeListener() { 94 | @Override 95 | public void onChanged(Change change) { 96 | selectedIndexes.setAll(change.getList()); 97 | } 98 | }); 99 | 100 | //Setting the items for columns selection 101 | colSelect.setItems(tableView.getColumns()); 102 | for (TableColumn c : colSelect.getItems()) { 103 | setCellColumnSelection(c); 104 | } 105 | 106 | //add listener and update of selection type 107 | colSelect.valueProperty().addListener(new ChangeListener>() { 108 | @Override 109 | public void changed( 110 | ObservableValue> ov, 111 | TableColumn t, 112 | final TableColumn t1) { 113 | if (t1 != null) { 114 | if (cellRadio.isSelected()) { 115 | setCellSelection(); 116 | } 117 | } 118 | 119 | } 120 | }); 121 | 122 | 123 | //For showing the column name properly 124 | colSelect.setConverter(new StringConverter>() { 125 | @Override 126 | public String toString(TableColumn t) { 127 | if(t== null ){ 128 | return ""; 129 | } 130 | return t.getText(); 131 | } 132 | 133 | @Override 134 | public TableColumn fromString(String string) { 135 | for (TableColumn t : colSelect.getItems()) { 136 | if (t.getText().equals(string)) { 137 | return t; 138 | } 139 | } 140 | return null; 141 | } 142 | }); 143 | 144 | //the radio buttons change property listener [Row/Cell] selection 145 | selectionGrp.selectedToggleProperty().addListener(new ChangeListener() { 146 | @Override 147 | public void changed( 148 | ObservableValue ov, Toggle t, Toggle t1) { 149 | if (t1 == cellRadio) { 150 | setCellSelection(); 151 | } else { 152 | setRowSelection(); 153 | } 154 | 155 | } 156 | }); 157 | //Stricting the Column selection 158 | colSelect.disableProperty().bind(cellRadio.selectedProperty().not()); 159 | 160 | //set the Row Factory of the table 161 | setRowFactory(); 162 | 163 | //Set row selection as default 164 | setRowSelection(); 165 | } 166 | 167 | private void setCellValueFactories() { 168 | snCol.setCellValueFactory(new PropertyValueFactory("sn")); 169 | nameCol.setCellValueFactory(new PropertyValueFactory("name")); 170 | genderCol.setCellValueFactory(new PropertyValueFactory("gender")); 171 | phoneCol.setCellValueFactory(new PropertyValueFactory("phone")); 172 | addressCol.setCellValueFactory(new PropertyValueFactory("address")); 173 | } 174 | 175 | /** 176 | * Change the cell selection boolean value of TableView 177 | */ 178 | public void setRowSelection() { 179 | tableView.getSelectionModel().clearSelection(); 180 | tableView.getSelectionModel().setCellSelectionEnabled(false); 181 | } 182 | 183 | /** 184 | * Change the cell selection boolean value of TableView 185 | */ 186 | public void setCellSelection() { 187 | tableView.getSelectionModel().clearSelection(); 188 | tableView.getSelectionModel().setCellSelectionEnabled(true); 189 | 190 | } 191 | 192 | /** 193 | * Set Row Factory for the TableView 194 | */ 195 | public void setRowFactory() { 196 | tableView.setRowFactory(new Callback, TableRow>() { 197 | @Override 198 | public TableRow call(TableView p) { 199 | final TableRow row = new TableRow(); 200 | row.setOnDragEntered(new EventHandler() { 201 | @Override 202 | public void handle(DragEvent t) { 203 | setSelection(row); 204 | } 205 | }); 206 | 207 | row.setOnDragDetected(new EventHandler() { 208 | @Override 209 | public void handle(MouseEvent t) { 210 | if (rowRadio.isSelected()) { 211 | Dragboard db = row.getTableView().startDragAndDrop(TransferMode.COPY); 212 | ClipboardContent content = new ClipboardContent(); 213 | content.put(dataFormat, "XData"); 214 | db.setContent(content); 215 | setSelection(row); 216 | t.consume(); 217 | } 218 | } 219 | }); 220 | return row; 221 | } 222 | }); 223 | } 224 | 225 | /** 226 | * This function helps to make the Cell Factory for specific TableColumn 227 | * 228 | * @param col 229 | */ 230 | public void setCellColumnSelection(final TableColumn col) { 231 | col.setCellFactory(new Callback, TableCell>() { 232 | @Override 233 | public TableCell call( 234 | TableColumn p) { 235 | final TableCell cell = new TableCell() { 236 | @Override 237 | protected void updateItem(Object t, boolean bln) { 238 | super.updateItem(t, bln); 239 | if (t != null) { 240 | setText(t.toString()); 241 | } 242 | } 243 | }; 244 | 245 | cell.setOnDragEntered(new EventHandler() { 246 | @Override 247 | public void handle(DragEvent t) { 248 | setSelection(cell, col); 249 | } 250 | }); 251 | 252 | cell.setOnDragDetected(new EventHandler() { 253 | @Override 254 | public void handle(MouseEvent t) { 255 | if (cellRadio.isSelected() && colSelect.getValue() == col) { 256 | Dragboard db = cell.getTableView().startDragAndDrop(TransferMode.COPY); 257 | ClipboardContent content = new ClipboardContent(); 258 | content.put(dataFormat, "XData"); 259 | db.setContent(content); 260 | setSelection(cell, col); 261 | t.consume(); 262 | } 263 | } 264 | }); 265 | return cell; 266 | 267 | } 268 | }); 269 | } 270 | 271 | /** 272 | * For the changes on table cell selection used only on the TableCell selection mode 273 | * 274 | * @param cell 275 | */ 276 | private void setSelection(IndexedCell cell) { 277 | if (rowRadio.isSelected()) { 278 | if (cell.isSelected()) { 279 | System.out.println("False"); 280 | tableView.getSelectionModel().clearSelection(cell.getIndex()); 281 | } else { 282 | System.out.println("true"); 283 | tableView.getSelectionModel().select(cell.getIndex()); 284 | } 285 | } 286 | 287 | } 288 | 289 | /** 290 | * For the changes on the table row selection used only on TableRow selection mode 291 | * 292 | * @param cell 293 | * @param col 294 | */ 295 | private void setSelection(IndexedCell cell, TableColumn col) { 296 | if (cellRadio.isSelected()) { 297 | if (cell.isSelected()) { 298 | System.out.println("False enter"); 299 | tableView.getSelectionModel().clearSelection(cell.getIndex(), col); 300 | } else { 301 | System.out.println("Select"); 302 | tableView.getSelectionModel().select(cell.getIndex(), col); 303 | } 304 | } 305 | } 306 | 307 | /** 308 | * Provides the Dummy Data for this application in string format 309 | * 310 | * @param length 311 | * @return String 312 | */ 313 | public String getDummyText(int length) { 314 | String most = "abdflntiso"; 315 | String alpha = "abcdefghijkmopqrstuvwxyz"; 316 | StringBuffer b = new StringBuffer(); 317 | int chars = 0; 318 | for (int i = 0; i < length; i++) { 319 | if (chars > 2 && chars > Math.random() * 10) { 320 | b.append(" "); 321 | chars = 0; 322 | continue; 323 | } 324 | if (chars == 0 || i % 2 == 0) { 325 | b.append(most.charAt((int)(Math.random() * most.length()))); 326 | } else { 327 | b.append(alpha.charAt((int)(Math.random() * alpha.length()))); 328 | } 329 | chars++; 330 | } 331 | return b.toString(); 332 | } 333 | 334 | /** 335 | * Provides the dummy String 336 | * 337 | * @param length 338 | * @return 339 | */ 340 | public String getDummyDigits(int length) { 341 | 342 | StringBuilder b = new StringBuilder(); 343 | for (int i = 0; i < length; i++) { 344 | b.append((int)(Math.random() * 9)); 345 | } 346 | return b.toString(); 347 | } 348 | 349 | /** 350 | * Provides the dummy Person data. 351 | * 352 | * @return 353 | */ 354 | public ObservableList getData() { 355 | String[] names = new String[]{"Narayan", "Phil", "Pablo", "Michael", "Mike", "Timur", "Oszkar", "David"}; 356 | 357 | ObservableList persons = FXCollections.observableArrayList(); 358 | for (int i = 1; i < 500; i++) { 359 | Person p = new Person(); 360 | p.setSn(i); 361 | p.setName(names[(int)(Math.random() * names.length)]); 362 | p.setAddress(getDummyText(15)); 363 | p.setPhone(getDummyDigits(9)); 364 | p.setGender(Gender.values()[i % 3]); 365 | persons.add(p); 366 | } 367 | return persons; 368 | } 369 | } 370 | -------------------------------------------------------------------------------- /src/main/java/np/com/ngopal/tableviewdataselection/TableViewDataSelection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | package np.com.ngopal.tableviewdataselection; 6 | 7 | import java.io.IOException; 8 | import java.util.logging.Level; 9 | import java.util.logging.Logger; 10 | import javafx.application.Application; 11 | import javafx.fxml.FXMLLoader; 12 | import javafx.scene.Scene; 13 | import javafx.scene.control.Label; 14 | import javafx.scene.layout.BorderPane; 15 | import javafx.scene.layout.Pane; 16 | import javafx.stage.Stage; 17 | 18 | /** 19 | * 20 | * @author Narayan G. Maharjan 21 | */ 22 | public class TableViewDataSelection extends Application { 23 | @Override 24 | public void start(Stage primaryStage) { 25 | Pane p = null; 26 | try { 27 | p = FXMLLoader.load(getClass().getResource("/fxml/TableViewDataFXML.fxml")); 28 | } catch (IOException ex) { 29 | p = new BorderPane(); 30 | Label l = new Label("Error on FXML loading:" + ex.getMessage()); 31 | p.getChildren().add(l); 32 | Logger.getLogger(TableViewDataSelection.class.getName()).log(Level.SEVERE, null, ex); 33 | } 34 | 35 | 36 | Scene scene = new Scene(p); 37 | 38 | primaryStage.setTitle("TableView Data Selection Demo !"); 39 | primaryStage.setScene(scene); 40 | primaryStage.show(); 41 | } 42 | 43 | /** 44 | * The main() method is ignored in correctly deployed JavaFX 45 | * application. main() serves only as fallback in case the 46 | * application can not be launched through deployment artifacts, 47 | * e.g., in IDEs with limited FX support. NetBeans ignores main(). 48 | * 49 | * @param args the command line arguments 50 | */ 51 | public static void main(String[] args) { 52 | launch(args); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/resources/fxml/TableViewDataFXML.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | --------------------------------------------------------------------------------