日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

【JavaFx教程】第三部分:与用户的交互

發(fā)布時(shí)間:2024/4/15 java 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【JavaFx教程】第三部分:与用户的交互 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

第3部分的主題:

  • 在表中反應(yīng)選擇的改變(TableView中)。
  • 增加增加編輯刪除按鈕的功能。
  • 創(chuàng)建自定義彈出對(duì)話框編輯人員。
  • 驗(yàn)證用戶輸入。

  • 響應(yīng)表的選擇

    顯然,我們還沒(méi)有使用應(yīng)用程序的右邊。想法是當(dāng)用戶選擇表中的人員時(shí),在右邊顯示人員的詳情。

    首先,讓我們?cè)赑ersonOverviewController添加一個(gè)新的方法,幫助我們使用單個(gè)人員的數(shù)據(jù)填寫標(biāo)簽。

    創(chuàng)建方法showPersonDetails(Person person)。遍歷所有標(biāo)簽,并且使用setText(…)方法設(shè)置標(biāo)簽的文本為個(gè)人的詳情。如果null作為參數(shù)傳遞,所有的標(biāo)簽應(yīng)該被清空。

    PersonOverviewController.java

    /*** Fills all text fields to show details about the person.* If the specified person is null, all text fields are cleared.* * @param person the person or null*/ private void showPersonDetails(Person person) {if (person != null) {// Fill the labels with info from the person object.firstNameLabel.setText(person.getFirstName());lastNameLabel.setText(person.getLastName());streetLabel.setText(person.getStreet());postalCodeLabel.setText(Integer.toString(person.getPostalCode()));cityLabel.setText(person.getCity());// TODO: We need a way to convert the birthday into a String! // birthdayLabel.setText(...);} else {// Person is null, remove all the text.firstNameLabel.setText("");lastNameLabel.setText("");streetLabel.setText("");postalCodeLabel.setText("");cityLabel.setText("");birthdayLabel.setText("");} }

    轉(zhuǎn)換生日日期為字符串

    你注意到我們沒(méi)有設(shè)置birthday到標(biāo)簽中,因?yàn)樗荓ocalDate類型,不是String。我們首先需要格式化日期。

    在幾個(gè)地方上我們使用LocalDate和String之間的轉(zhuǎn)換。好的實(shí)踐是創(chuàng)建一個(gè)帶有static方法的幫助類。我們稱它為DateUtil,并且把它放到單獨(dú)的包中,稱為ch.makery.address.util。

    DateUtil.java

    package ch.makery.address.util;import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException;/*** Helper functions for handling dates.* * @author Marco Jakob*/ public class DateUtil {/** The date pattern that is used for conversion. Change as you wish. */private static final String DATE_PATTERN = "dd.MM.yyyy";/** The date formatter. */private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(DATE_PATTERN);/*** Returns the given date as a well formatted String. The above defined * {@link DateUtil#DATE_PATTERN} is used.* * @param date the date to be returned as a string* @return formatted string*/public static String format(LocalDate date) {if (date == null) {return null;}return DATE_FORMATTER.format(date);}/*** Converts a String in the format of the defined {@link DateUtil#DATE_PATTERN} * to a {@link LocalDate} object.* * Returns null if the String could not be converted.* * @param dateString the date as String* @return the date object or null if it could not be converted*/public static LocalDate parse(String dateString) {try {return DATE_FORMATTER.parse(dateString, LocalDate::from);} catch (DateTimeParseException e) {return null;}}/*** Checks the String whether it is a valid date.* * @param dateString* @return true if the String is a valid date*/public static boolean validDate(String dateString) {// Try to parse the String.return DateUtil.parse(dateString) != null;} }

    提示:你能通過(guò)改變DATE_PATTERN修改日期的格式。所有可能的格式參考?DateTimeFormatter.

    使用DateUtil

    現(xiàn)在,我們需要在PersonOverviewController的showPersonDetails方法中使用我們新建的DateUtil。使用下面這樣替代我們添加的TODO。

    birthdayLabel.setText(DateUtil.format(person.getBirthday()));

    監(jiān)聽表選擇的改變

    為了當(dāng)用戶在人員表中選擇一個(gè)人時(shí)獲得通知,我們需要監(jiān)聽改變。

    在JavaFX中有一個(gè)接口稱為ChangeListener,帶有一個(gè)方法changed()。該方法有三個(gè)參數(shù):observable,?oldValue和newValue。

    我們使用*Java 8 lambda*表達(dá)式創(chuàng)建這樣一個(gè)ChangeListener。讓我們添加一些行到PersonOverviewController的initialize()方法中?,F(xiàn)在看起來(lái)是這樣的。

    PersonOverviewController.java

    @FXML private void initialize() {// Initialize the person table with the two columns.firstNameColumn.setCellValueFactory(cellData -> cellData.getValue().firstNameProperty());lastNameColumn.setCellValueFactory(cellData -> cellData.getValue().lastNameProperty());// Clear person details.showPersonDetails(null);// Listen for selection changes and show the person details when changed.personTable.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> showPersonDetails(newValue)); }

    使用showPersonDetails(null),我們重設(shè)個(gè)人詳情。

    使用personTable.getSelectionModel...,我們獲得人員表的selectedItemProperty,并且添加監(jiān)聽。不管什么時(shí)候用戶選擇表中的人員,都會(huì)執(zhí)行我們的lambda表達(dá)式。我們獲取新選擇的人員,并且把它傳遞給showPersonDetails(...)方法。

    現(xiàn)在試著運(yùn)行你的應(yīng)用程序,驗(yàn)證當(dāng)你選擇表中的人員時(shí),關(guān)于該人員的詳情是否正確的顯示。

    如果有些事情不能工作,你可以對(duì)比下PersonOverviewController.java中的PersonOverviewController類


    刪除按鈕

    我們的用戶接口已經(jīng)包含一個(gè)刪除按鈕,但是沒(méi)有任何功能。我們能在*SceneBuilder*中的按鈕上選擇動(dòng)作。在我們控制器中的任何使用@FXML(或者它是公用的)注釋的方法都可以被*Scene Builder*訪問(wèn)。因此,讓我們?cè)赑ersonOverviewController類的最后添加一個(gè)刪除方法。

    PersonOverviewController.java

    /*** Called when the user clicks on the delete button.*/ @FXML private void handleDeletePerson() {int selectedIndex = personTable.getSelectionModel().getSelectedIndex();personTable.getItems().remove(selectedIndex); }

    現(xiàn)在,使用*SceneBuilder*打開PersonOverview.fxml文件,選擇*Delete*按鈕,打開*Code*組,在On Actin的下拉菜單中選擇handleDeletePerson。

    錯(cuò)誤處理

    如果你現(xiàn)在運(yùn)行應(yīng)用程序,你應(yīng)該能夠從表中刪除選擇的人員。但是,當(dāng)你沒(méi)有在表中選擇人員時(shí)點(diǎn)擊刪除按鈕時(shí)會(huì)發(fā)生什么呢。

    這里有一個(gè)ArrayIndexOutOfBoundsException,因?yàn)樗荒軇h除掉索引為-1人員項(xiàng)目。索引-1由getSelectedIndex()返回,它意味著你沒(méi)有選擇項(xiàng)目。

    當(dāng)然,忽略這種錯(cuò)誤不是非常好。我們應(yīng)該讓用戶知道在刪除時(shí)必須選擇一個(gè)人員。(更好的是我們應(yīng)該禁用刪除按鈕,以便用戶沒(méi)有機(jī)會(huì)做錯(cuò)誤的事情)。

    我們添加一個(gè)彈出對(duì)話框通知用戶,你將需要*添加一個(gè)庫(kù)Dialogs:

  • 下載controlsfx-8.0.6_20.jar?(你也能從ControlsFX Website中獲取)。?重要:ControlsFX必須是8.0.6_20以上版本才能在JDK8U20以上版本工作。
  • 在項(xiàng)目中創(chuàng)建一個(gè)lib子目錄,添加controlsf jar文件到該目錄下。
  • 添加庫(kù)到你的項(xiàng)目classpath中。在Eclipse中右擊jar文件|選擇Build Path| *Add to Build Path*。現(xiàn)在Eclipse知道這個(gè)庫(kù)了。
  • 對(duì)handleDeletePerson()方法做一些修改后,不管什么時(shí)候用戶沒(méi)有選擇表中的人員時(shí)按下刪除按鈕,我們能顯示一個(gè)簡(jiǎn)單的對(duì)話框。

    PersonOverviewController.java

    /*** Called when the user clicks on the delete button.*/ @FXML private void handleDeletePerson() {int selectedIndex = personTable.getSelectionModel().getSelectedIndex();if (selectedIndex >= 0) {personTable.getItems().remove(selectedIndex);} else {// Nothing selected.Dialogs.create().title("No Selection").masthead("No Person Selected").message("Please select a person in the table.").showWarning();} }

    更多如何使用Dialog的示例,請(qǐng)閱讀JavaFX 8 Dialogs.


    新建和編輯對(duì)話框

    新建和編輯的動(dòng)作有點(diǎn)工作:我們需要一個(gè)自定義帶表單的對(duì)話框(例如:新的Stage),詢問(wèn)用戶關(guān)于人員的詳情。

    設(shè)計(jì)對(duì)話框

  • 在*view*包中創(chuàng)建新的fxml文件,稱為PersonEditDialog.fxml?

  • 使用GridPan,Label,TextField和Button創(chuàng)建一個(gè)對(duì)話框,如下所示:

  • 如果你不能完成工作,你能下載這個(gè)PersonEditDialog.fxml.

    創(chuàng)建控制器

    為對(duì)話框創(chuàng)建控制器PersonEditDialogController.java:

    PersonEditDialogController.java

    package ch.makery.address.view;import javafx.fxml.FXML; import javafx.scene.control.TextField; import javafx.stage.Stage;import org.controlsfx.dialog.Dialogs;import ch.makery.address.model.Person; import ch.makery.address.util.DateUtil;/*** Dialog to edit details of a person.* * @author Marco Jakob*/ public class PersonEditDialogController {@FXMLprivate TextField firstNameField;@FXMLprivate TextField lastNameField;@FXMLprivate TextField streetField;@FXMLprivate TextField postalCodeField;@FXMLprivate TextField cityField;@FXMLprivate TextField birthdayField;private Stage dialogStage;private Person person;private boolean okClicked = false;/*** Initializes the controller class. This method is automatically called* after the fxml file has been loaded.*/@FXMLprivate void initialize() {}/*** Sets the stage of this dialog.* * @param dialogStage*/public void setDialogStage(Stage dialogStage) {this.dialogStage = dialogStage;}/*** Sets the person to be edited in the dialog.* * @param person*/public void setPerson(Person person) {this.person = person;firstNameField.setText(person.getFirstName());lastNameField.setText(person.getLastName());streetField.setText(person.getStreet());postalCodeField.setText(Integer.toString(person.getPostalCode()));cityField.setText(person.getCity());birthdayField.setText(DateUtil.format(person.getBirthday()));birthdayField.setPromptText("dd.mm.yyyy");}/*** Returns true if the user clicked OK, false otherwise.* * @return*/public boolean isOkClicked() {return okClicked;}/*** Called when the user clicks ok.*/@FXMLprivate void handleOk() {if (isInputValid()) {person.setFirstName(firstNameField.getText());person.setLastName(lastNameField.getText());person.setStreet(streetField.getText());person.setPostalCode(Integer.parseInt(postalCodeField.getText()));person.setCity(cityField.getText());person.setBirthday(DateUtil.parse(birthdayField.getText()));okClicked = true;dialogStage.close();}}/*** Called when the user clicks cancel.*/@FXMLprivate void handleCancel() {dialogStage.close();}/*** Validates the user input in the text fields.* * @return true if the input is valid*/private boolean isInputValid() {String errorMessage = "";if (firstNameField.getText() == null || firstNameField.getText().length() == 0) {errorMessage += "No valid first name!\n"; }if (lastNameField.getText() == null || lastNameField.getText().length() == 0) {errorMessage += "No valid last name!\n"; }if (streetField.getText() == null || streetField.getText().length() == 0) {errorMessage += "No valid street!\n"; }if (postalCodeField.getText() == null || postalCodeField.getText().length() == 0) {errorMessage += "No valid postal code!\n"; } else {// try to parse the postal code into an int.try {Integer.parseInt(postalCodeField.getText());} catch (NumberFormatException e) {errorMessage += "No valid postal code (must be an integer)!\n"; }}if (cityField.getText() == null || cityField.getText().length() == 0) {errorMessage += "No valid city!\n"; }if (birthdayField.getText() == null || birthdayField.getText().length() == 0) {errorMessage += "No valid birthday!\n";} else {if (!DateUtil.validDate(birthdayField.getText())) {errorMessage += "No valid birthday. Use the format dd.mm.yyyy!\n";}}if (errorMessage.length() == 0) {return true;} else {// Show the error message.Dialogs.create().title("Invalid Fields").masthead("Please correct invalid fields").message(errorMessage).showError();return false;}} }

    關(guān)于該控制器的一些事情應(yīng)該注意:

  • setPerson(…)方法可以從其它類中調(diào)用,用來(lái)設(shè)置編輯的人員。
  • 當(dāng)用戶點(diǎn)擊OK按鈕時(shí),調(diào)用handleOK()方法。首先,通過(guò)調(diào)用isInputValid()方法做一些驗(yàn)證。只有驗(yàn)證成功,Person對(duì)象使用輸入的數(shù)據(jù)填充。這些修改將直接應(yīng)用到Person對(duì)象上,傳遞給setPerson(…)。
  • 布爾值okClicked被使用,以便調(diào)用者決定用戶是否點(diǎn)擊OK或者Cancel按鈕。
  • 連接視圖和控制器

    使用已經(jīng)創(chuàng)建的視圖(FXML)和控制器,需要連接到一起。

  • 使用SceneBuilder打開PersonEditDialog.fxml文件
  • 在左邊的*Controller*組中選擇PersonEditDialogController作為控制器類
  • 設(shè)置所有TextField的fx:id到相應(yīng)的控制器字段上。
  • 設(shè)置兩個(gè)按鈕的onAction到相應(yīng)的處理方法上。
  • 打開對(duì)話框

    在MainApp中添加一個(gè)方法加載和顯示編輯人員的對(duì)話框。

    MainApp.java

    /*** Opens a dialog to edit details for the specified person. If the user* clicks OK, the changes are saved into the provided person object and true* is returned.* * @param person the person object to be edited* @return true if the user clicked OK, false otherwise.*/ public boolean showPersonEditDialog(Person person) {try {// Load the fxml file and create a new stage for the popup dialog.FXMLLoader loader = new FXMLLoader();loader.setLocation(MainApp.class.getResource("view/PersonEditDialog.fxml"));AnchorPane page = (AnchorPane) loader.load();// Create the dialog Stage.Stage dialogStage = new Stage();dialogStage.setTitle("Edit Person");dialogStage.initModality(Modality.WINDOW_MODAL);dialogStage.initOwner(primaryStage);Scene scene = new Scene(page);dialogStage.setScene(scene);// Set the person into the controller.PersonEditDialogController controller = loader.getController();controller.setDialogStage(dialogStage);controller.setPerson(person);// Show the dialog and wait until the user closes itdialogStage.showAndWait();return controller.isOkClicked();} catch (IOException e) {e.printStackTrace();return false;} }

    添加下面的方法到PersonOverviewController中。當(dāng)用戶按下*New*或*Edit*按鈕時(shí),這些方法將從MainApp中調(diào)用showPersonEditDialog(...)。

    PersonOverviewController.java

    /*** Called when the user clicks the new button. Opens a dialog to edit* details for a new person.*/ @FXML private void handleNewPerson() {Person tempPerson = new Person();boolean okClicked = mainApp.showPersonEditDialog(tempPerson);if (okClicked) {mainApp.getPersonData().add(tempPerson);} }/*** Called when the user clicks the edit button. Opens a dialog to edit* details for the selected person.*/ @FXML private void handleEditPerson() {Person selectedPerson = personTable.getSelectionModel().getSelectedItem();if (selectedPerson != null) {boolean okClicked = mainApp.showPersonEditDialog(selectedPerson);if (okClicked) {showPersonDetails(selectedPerson);}} else {// Nothing selected.Dialogs.create().title("No Selection").masthead("No Person Selected").message("Please select a person in the table.").showWarning();} }

    在Scene Builder中打開PersonOverview.fxml文件,為New和Edit按鈕的*On Action*中選擇對(duì)應(yīng)的方法。


    完成!

    現(xiàn)在你應(yīng)該有一個(gè)可以工作的*Address應(yīng)用*。應(yīng)用能夠添加、編輯和刪除人員。這里甚至有一些文本字段的驗(yàn)證避免壞的用戶輸入。

    我希望本應(yīng)用的概念和結(jié)構(gòu)讓開始編寫自己的JavaFX應(yīng)用!玩的開心。

    --------------------- 本文來(lái)自 jobbible 的CSDN 博客 ,全文地址請(qǐng)點(diǎn)擊:https://blog.csdn.net/moshenglv/article/details/82877639?utm_source=copy?

    轉(zhuǎn)載于:https://www.cnblogs.com/jobbible/p/9718449.html

    總結(jié)

    以上是生活随笔為你收集整理的【JavaFx教程】第三部分:与用户的交互的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。