All of the source code in this example is available on GitHub.
The main view of this JavaFX application contains a TextField and a Button. Pressing the Button will launch a Popup.
Popup Displayed When Empl Button Pressed |
Main View
The Java main() and start(), ListViewHelperApp, loads the ListViewHelperMain.fxml file.
ListViewHelperMain.fxml and ListViewHelperController implement the "ListView Helper" window in the above screenshot. The following is the code from ListViewHelperController. The position for the Empl Button, a reference to the target TextField, and the Window are passed along to a JavaFX Popup subclass.
@FXML TextField tfEmployee; @FXML public void clear() { tfEmployee.setText( "" ); } @FXML public void showEmployeesHelper(ActionEvent evt) { Button btn = (Button)evt.getSource(); Point2D point = btn.localToScreen(0.0d + btn.getWidth(), 0.0d - btn.getHeight()); try { Popup employeesHelper = new ListViewHelperEmployeesPopup(tfEmployee, point); employeesHelper.show(btn.getScene().getWindow()); } catch(Exception exc) { exc.printStackTrace(); Alert alert = new Alert(AlertType.ERROR, "Error creating employees popup; exiting"); alert.showAndWait(); btn.getScene().getWindow().hide(); // close and implicit exit } }
Employees View
The Employees View -- the list of employees -- is a very small class that fills the ListView. It is implemented with ListViewHelperEmployees.fxml and ListViewHelperEmployeesController. The following is from ListViewHelperEmployeesController.
@FXML ListViewlvEmployees; @FXML public void initialize() { lvEmployees.getItems().addAll( "Adams, John", "Lincoln, Abe", "Washington, George" }; }
Popup Subclass
The Popup subclass ListViewHelperEmployeesPopup creates the Employees View through an FXMLLoader. It also puts the selection handler on the Employees View's ListView member. The subclass constructor initializes the Popup Stage. The initialization positions the popup, sets the autoHide property, and adds the content.
There is an animation that I put on the Popup when hidden. See the following video for a detailed discussion of that code.
The following is the Popup subclass' constructor.
public ListViewHelperEmployeesPopup(TextField tfTarget, Point2D position) throws Exception{ final WeakReferencetfTargetRef = new WeakReference<>(tfTarget); FXMLLoader fxmlLoader = new FXMLLoader(ListViewHelperApp.class.getResource("/ListViewHelperEmployees.fxml")); Parent content = fxmlLoader.load(); ListViewHelperEmployeesController controller = fxmlLoader.getController(); controller .lvEmployees .getSelectionModel() .selectedItemProperty() .addListener((obs, oldValue, newValue) -> { if( newValue != null ) { tfTargetRef.get().setText( newValue ); // no delay -- and no feedback //ListViewHelperEmployeesPopup.this.hide(); // slight delay + gentle fade -- maintains highlight Duration duration = new Duration( 300 ); KeyValue kvOpacity = new KeyValue(content.opacityProperty(), 0); KeyFrame atEndFrame = new KeyFrame( duration, (evt) -> ListViewHelperEmployeesPopup.this.hide(), kvOpacity ); Timeline timeline = new Timeline(); timeline.getKeyFrames().add( atEndFrame ); timeline.play(); } }); setX( position.getX() ); setY( position.getY() ); setAutoHide(true); getContent().add( content ); }
In some cases, it may be easier to work with a ComboBox subclass rather than a special purpose Popup to enhance TextFields. However, I like to use FXML to build more complicated UIs. This approach will scale should the Popup UI need to grow.
All of the source code in this example is available on GitHub.
No comments:
Post a Comment