mirror of
				https://gitlab.com/kauron/jstudy
				synced 2025-10-26 08:08:38 +01:00 
			
		
		
		
	Table: new editing and filtering
* Split buttons between the context menu and above the table. * Moved adding/editing to above the table. * Added filtering. * Added shortcut to edit (double click) and to delete rows.
This commit is contained in:
		
					parent
					
						
							
								93b7dce200
							
						
					
				
			
			
				commit
				
					
						7fe80b07ec
					
				
			
		
					 2 changed files with 76 additions and 57 deletions
				
			
		|  | @ -1,50 +1,47 @@ | |||
| package es.kauron.jstudy.controller; | ||||
| 
 | ||||
| import es.kauron.jstudy.Main; | ||||
| import es.kauron.jstudy.model.AppPrefs; | ||||
| import es.kauron.jstudy.model.TestItem; | ||||
| import javafx.beans.property.BooleanProperty; | ||||
| import javafx.beans.property.SimpleBooleanProperty; | ||||
| import javafx.beans.property.SimpleStringProperty; | ||||
| import javafx.beans.property.StringProperty; | ||||
| import javafx.beans.binding.Bindings; | ||||
| import javafx.beans.property.*; | ||||
| import javafx.collections.FXCollections; | ||||
| import javafx.collections.ListChangeListener; | ||||
| import javafx.collections.ObservableList; | ||||
| import javafx.collections.transformation.FilteredList; | ||||
| import javafx.event.ActionEvent; | ||||
| import javafx.fxml.FXML; | ||||
| import javafx.fxml.FXMLLoader; | ||||
| import javafx.fxml.Initializable; | ||||
| import javafx.scene.Parent; | ||||
| import javafx.scene.Scene; | ||||
| import javafx.scene.control.Button; | ||||
| import javafx.scene.control.SelectionMode; | ||||
| import javafx.scene.control.TableColumn; | ||||
| import javafx.scene.control.TableView; | ||||
| import javafx.scene.control.*; | ||||
| import javafx.scene.input.KeyCode; | ||||
| import javafx.scene.input.KeyEvent; | ||||
| import javafx.scene.input.MouseEvent; | ||||
| import javafx.stage.FileChooser; | ||||
| import javafx.stage.Modality; | ||||
| import javafx.stage.Stage; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.net.URL; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.ResourceBundle; | ||||
| import java.util.*; | ||||
| 
 | ||||
| public class TableController implements Initializable { | ||||
|     @FXML | ||||
|     private TableView<TestItem> table; | ||||
|     @FXML | ||||
|     private TextField newQuestionField, newAnswerField, searchField; | ||||
|     @FXML | ||||
|     private Button addButton; | ||||
|     @FXML | ||||
|     private TableColumn<TestItem, String> answerCol, questionCol; | ||||
| 
 | ||||
|     private FilteredList<TestItem> filtered; | ||||
|     private ObservableList<TestItem> data; | ||||
|     private Controller parent; | ||||
|     private File file; | ||||
|     StringProperty name; | ||||
|     final BooleanProperty saved = new SimpleBooleanProperty(); | ||||
|     private final ObjectProperty<TestItem> editing = new SimpleObjectProperty<>(null); | ||||
| 
 | ||||
|     @Override | ||||
|     public void initialize(URL url, ResourceBundle resourceBundle) { | ||||
|         addButton.textProperty().bind(Bindings.when(editing.isNull()).then("_Add item").otherwise("_Save item")); | ||||
|         // Add context menu to Table | ||||
|         MenuItem menuEdit = new MenuItem("_Edit"); | ||||
|         menuEdit.setOnAction(this::onEditAction); | ||||
|  | @ -61,16 +58,18 @@ public class TableController implements Initializable { | |||
|         table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); | ||||
|         answerCol.setCellValueFactory(e -> e.getValue().answerProperty()); | ||||
|         questionCol.setCellValueFactory(e -> e.getValue().questionProperty()); | ||||
|         table.getSelectionModel().getSelectedIndices().addListener((ListChangeListener<? super Integer>) obs -> { | ||||
|             menuEdit.setDisable(obs.getList().size() != 1); | ||||
|         }); | ||||
|         table.getSelectionModel().getSelectedIndices().addListener( | ||||
|                 (ListChangeListener<? super Integer>) obs -> menuEdit.setDisable(obs.getList().size() != 1)); | ||||
|         searchField.textProperty().addListener((obj, o, n) -> | ||||
|                 filtered.setPredicate((item) -> item.getQuestion().contains(n) || item.getAnswer().contains(n))); | ||||
|     } | ||||
| 
 | ||||
|     void setData(String name, List<TestItem> list, Controller controller, File file) { | ||||
|         this.name = new SimpleStringProperty(name); | ||||
|         this.data = FXCollections.observableArrayList(list); | ||||
|         this.filtered = data.filtered((item) -> true); | ||||
|         this.parent = controller; | ||||
|         table.setItems(data); | ||||
|         table.setItems(filtered); | ||||
|         this.file = file; | ||||
|         saved.set(file != null); | ||||
|     } | ||||
|  | @ -99,41 +98,31 @@ public class TableController implements Initializable { | |||
| 
 | ||||
|     @FXML | ||||
|     protected void onAddAction(ActionEvent event) { | ||||
|         try { | ||||
|             FXMLLoader loader = new FXMLLoader(Main.class.getResource("view/edit.fxml")); | ||||
|             Parent pRoot = loader.load(); | ||||
| 
 | ||||
|             ((EditController) loader.getController()).setList(data, saved); | ||||
| 
 | ||||
|             Stage stage = new Stage(); | ||||
|             stage.setTitle("New entry"); | ||||
|             stage.setScene(new Scene(pRoot)); | ||||
|             stage.initModality(Modality.APPLICATION_MODAL); | ||||
|             stage.showAndWait(); | ||||
|         } catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|         if (editing.get() == null) { | ||||
|             TestItem item = new TestItem(newQuestionField.getText().trim(), newAnswerField.getText().trim()); | ||||
|             data.add(item); | ||||
|             newQuestionField.setText(""); | ||||
|             newAnswerField.setText(""); | ||||
|             saved.set(false); | ||||
|         } else { | ||||
|             editing.get().answerProperty().set(newAnswerField.getText().trim()); | ||||
|             editing.get().questionProperty().set(newQuestionField.getText().trim()); | ||||
|             editing.set(null); | ||||
|             newQuestionField.setText(""); | ||||
|             newAnswerField.setText(""); | ||||
|         } | ||||
|         newQuestionField.requestFocus(); | ||||
|     } | ||||
| 
 | ||||
|     @FXML | ||||
|     protected void onEditAction(ActionEvent event) { | ||||
|         ObservableList<Integer> list = table.getSelectionModel().getSelectedIndices(); | ||||
|         ObservableList<TestItem> list = table.getSelectionModel().getSelectedItems(); | ||||
|         if (list.size() != 1) return; | ||||
|         int index = list.get(0); | ||||
|         try { | ||||
|             FXMLLoader loader = new FXMLLoader(Main.class.getResource("view/edit.fxml")); | ||||
|             Parent root = loader.load(); | ||||
| 
 | ||||
|             ((EditController) loader.getController()).setList(table.getItems(), index, saved); | ||||
| 
 | ||||
|             Stage stage = new Stage(); | ||||
|             stage.setTitle("Editing entry..."); | ||||
|             stage.setScene(new Scene(root)); | ||||
|             stage.initModality(Modality.APPLICATION_MODAL); | ||||
|             stage.showAndWait(); | ||||
|         } catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|         editing.set(list.get(0)); | ||||
|         newQuestionField.setText(list.get(0).getQuestion()); | ||||
|         newAnswerField.setText(list.get(0).getAnswer()); | ||||
|         saved.set(false); | ||||
|         newQuestionField.requestFocus(); | ||||
|     } | ||||
| 
 | ||||
|     @FXML | ||||
|  | @ -151,15 +140,14 @@ public class TableController implements Initializable { | |||
|     protected void onDuplicateAction(ActionEvent event) { | ||||
|         if (table.getSelectionModel().getSelectedIndices().size() > 0) saved.set(false); | ||||
|         for (int i : table.getSelectionModel().getSelectedIndices()) | ||||
|             table.getItems().add(new TestItem(table.getItems().get(i))); | ||||
|             data.add(new TestItem(filtered.get(i))); | ||||
|         table.requestFocus(); | ||||
|     } | ||||
| 
 | ||||
|     @FXML | ||||
|     protected void onDeleteAction(ActionEvent event) { | ||||
|         if (table.getSelectionModel().getSelectedIndices().size() > 0) saved.set(false); | ||||
|         for (int i : table.getSelectionModel().getSelectedIndices()) | ||||
|             table.getItems().remove(i); | ||||
|         data.removeAll(table.getSelectionModel().getSelectedItems()); | ||||
|         table.requestFocus(); | ||||
|     } | ||||
| 
 | ||||
|  | @ -170,6 +158,32 @@ public class TableController implements Initializable { | |||
| 
 | ||||
|     @FXML | ||||
|     protected void onTestAction(ActionEvent event) { | ||||
|         parent.newTest(data); | ||||
|         parent.newTest(filtered); | ||||
|     } | ||||
| 
 | ||||
|     @FXML | ||||
|     protected void onTableKeyEvent(KeyEvent event) { | ||||
|         if (event.getCode().equals(KeyCode.DELETE)) { | ||||
|             onDeleteAction(null); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private final Timer timer = new Timer(); | ||||
|     private TimerTask timerTask = null; | ||||
|     @FXML | ||||
|     protected void onTableMouseClicked(MouseEvent event) { | ||||
|         if (timerTask == null) { | ||||
|             timerTask = new TimerTask() { | ||||
|                 @Override | ||||
|                 public void run() { | ||||
|                     timerTask = null; | ||||
|                 } | ||||
|             }; | ||||
|             timer.schedule(timerTask, 200); | ||||
|         } else { | ||||
|             if (timerTask.cancel()) | ||||
|                 onEditAction(null); | ||||
|             timerTask = null; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -7,11 +7,14 @@ | |||
|   <children> | ||||
|     <HBox alignment="CENTER_LEFT" spacing="5.0"> | ||||
|       <children> | ||||
|         <Button defaultButton="true" onAction="#onAddAction" prefWidth="105.0" text="_Add new"> | ||||
|         <TextField fx:id="newQuestionField" promptText="Question" /> | ||||
|         <TextField fx:id="newAnswerField"   promptText="Answer"   /> | ||||
|         <Button defaultButton="true" fx:id="addButton" onAction="#onAddAction" prefWidth="105.0" text="_Add new"> | ||||
|           <tooltip> | ||||
|             <Tooltip text="Add a new entry to the table" /> | ||||
|           </tooltip> | ||||
|         </Button> | ||||
|         <TextField fx:id="searchField" promptText="Search..." /> | ||||
|         <HBox alignment="CENTER_RIGHT" spacing="5.0" HBox.hgrow="ALWAYS" VBox.vgrow="ALWAYS"> | ||||
|           <children> | ||||
|             <Button layoutX="10.0" layoutY="273.0" onAction="#onTestAction" prefWidth="105.0" text="_Test all"> | ||||
|  | @ -35,7 +38,9 @@ | |||
|             <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> | ||||
|          </VBox.margin> | ||||
|     </HBox> | ||||
|     <TableView fx:id="table" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="400.0" HBox.hgrow="ALWAYS" VBox.vgrow="ALWAYS"> | ||||
|     <TableView fx:id="table" onMouseClicked="#onTableMouseClicked" onKeyPressed="#onTableKeyEvent" maxHeight="1.7976931348623157E308" | ||||
|                maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" | ||||
|                prefHeight="200.0" prefWidth="400.0" HBox.hgrow="ALWAYS" VBox.vgrow="ALWAYS"> | ||||
|       <columns> | ||||
|         <TableColumn fx:id="questionCol" prefWidth="75.0" text="Question" /> | ||||
|         <TableColumn fx:id="answerCol" prefWidth="75.0" text="Answer" /> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue