项目简介:
基于java 的通讯录管理系统。
使用javafx进行界面开发设计,程序包含添加和删除分组、个人主页(含图片等个人信息等等)、增删改查个人信息、模糊搜索、打开xml文件、打开csv(有格式要求)文件、打开vCard(有格式要求)文件、导出为xml文件、导出为csv文件、导出为vCard文件以及基本的新建保存文件功能,是一个小练习。
本程序采用Intellij IDEA 2024.1平台进行开发,使用JavaFX Scene Builder 2.0辅助界面设计,jdk版本为1.8.0_281。
另外,程序中导入了pinyin4j-2.5.0.jar包以及ez-vcard-0.12.1.jar包,如果出现找不到包的问题可以自行导入。
本程序参考学习了以下内容:
JavaFX 教程 (中文) | code.makery.ch
项目结构:
项目类图:
项目代码:
1.model包:
Person
package model;
import java.io.File;
import java.time.LocalDate;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import util.LocalDateAdapter;
public class Person {
private final StringProperty groupName;//所属组
private final StringProperty personName;//名字
private final StringProperty homeAddress;//家庭地址
private final IntegerProperty postalCode;//邮编
private final StringProperty workAddress;//工作地址&&单位
private final ObjectProperty<LocalDate> birthday;//生日
private final StringProperty phonenumber;//电话号码
private final StringProperty emailadd;//邮箱
private final StringProperty extralting;//备注
private String personimage;//图片(URL)
public Person() {
this(null, null);
}
//设置一些初始数据
public Person(String groupName, String personName) {
this.groupName = new SimpleStringProperty(groupName);
this.personName = new SimpleStringProperty(personName);
this.homeAddress = new SimpleStringProperty("泰山区学牲宿舍");
this.postalCode = new SimpleIntegerProperty(1234);
this.workAddress = new SimpleStringProperty("SCAU");
this.birthday = new SimpleObjectProperty<LocalDate>(LocalDate.of(2000, 2, 4));
this.phonenumber = new SimpleStringProperty("1145145178");
this.emailadd = new SimpleStringProperty("11111@163.com");
this.extralting = new SimpleStringProperty("圆神糕首");
File file = new File("src\\resources\\images\\man.png");
String s = file.toURI().toString();
this.personimage = s;
}
public String getgroupName() {
return groupName.get();
}
public void setgroupName(String groupName) {
this.groupName.set(groupName);
}
public StringProperty groupNameProperty() {
return groupName;
}
public String getPersonName() {
return personName.get();
}
public void setPersonName(String personName) {
this.personName.set(personName);
}
public StringProperty personNameProperty() {
return personName;
}
public String getHomeAddress() {
return homeAddress.get();
}
public void setHomeAddress(String homeAddress) {
this.homeAddress.set(homeAddress);
}
public StringProperty homeAddressProperty() {
return homeAddress;
}
public int getPostalCode() {
return postalCode.get();
}
public void setPostalCode(int postalCode) {
this.postalCode.set(postalCode);
}
public IntegerProperty postalCodeProperty() {
return postalCode;
}
public String getWorkAddress() {
return workAddress.get();
}
public void setWorkAddress(String workAddress) {
this.workAddress.set(workAddress);
}
public StringProperty workAddressProperty() {
return workAddress;
}
public void setPhonenumber(String phonenumber) {this.phonenumber.set(phonenumber);}
public String getPhonenumber() {return phonenumber.get();}
public StringProperty phonenumberProperty() {return phonenumber;}
public String getEmailadd() {return emailadd.get();}
public void setEmailadd(String emailadd) {this.emailadd.set(emailadd);}
public StringProperty emailaddProperty() {return emailadd;}
public String getExtralting() {return extralting.get();}
public void setExtralting(String extralting) {this.extralting.set(extralting);}
public StringProperty extraltingProperty() {return extralting;}
public String getPersonimage() {return personimage;}
public void setPersonimage(String personimage) {this.personimage=personimage;}
@XmlJavaTypeAdapter(LocalDateAdapter.class)
public LocalDate getBirthday() {
return birthday.get();
}
public void setBirthday(LocalDate birthday) {
this.birthday.set(birthday);
}
public ObjectProperty<LocalDate> birthdayProperty() {
return birthday;
}
}
PersonListWrapper
package model;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
//读取xml文件
@XmlRootElement(name = "persons")
public class PersonListWrapper {
private List<Person> persons;
@XmlElement(name = "person")
public List<Person> getPersons() {
return persons;
}
public void setPersons(List<Person> persons) {
this.persons = persons;
}
}
resources包:存资源图片
util包:
DateUtil
package util;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
public class DateUtil {
//设置生日格式
private static final String DATE_PATTERN = "yyyy.MM.dd";
private static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern(DATE_PATTERN);
public static String format(LocalDate date) {
if (date == null) {
return null;
}
return DATE_FORMATTER.format(date);
}
public static LocalDate parse(String dateString) {
try {
return DATE_FORMATTER.parse(dateString, LocalDate::from);
} catch (DateTimeParseException e) {
return null;
}
}
public static boolean validDate(String dateString) {
return DateUtil.parse(dateString) != null;
}
}
LocalDateAdapter
package util;
import java.time.LocalDate;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class LocalDateAdapter extends XmlAdapter<String, LocalDate> {
@Override
public LocalDate unmarshal(String v) throws Exception {
return LocalDate.parse(v);
}
@Override
public String marshal(LocalDate v) throws Exception {
return v.toString();
}
}
view包:
ChangeHanziToPinyin
package view;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
public class ChangeHanziToPinyin {
public static String getPinYin(String src) {
String t4 = "";
if (src != null) {
char[] t1 = src.toCharArray();
String[] t2 = new String[t1.length];
// 设置汉字拼音输出的格式
HanyuPinyinOutputFormat t3 = new HanyuPinyinOutputFormat();
t3.setCaseType(HanyuPinyinCaseType.LOWERCASE);
t3.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
t3.setVCharType(HanyuPinyinVCharType.WITH_V);
int t0 = t1.length;
try {
for (int i = 0; i < t0; i++) {
// 判断是否为汉字字符
if (Character.toString(t1[i]).matches("[\\u4E00-\\u9FA5]+")) {
// 将汉字的几种全拼都存到t2数组中
t2 = PinyinHelper.toHanyuPinyinStringArray(t1[i], t3);
// 取出该汉字全拼的第一种读音并连接到字符串t4后
t4 += t2[0];
} else {
// 如果不是汉字字符,直接取出字符并连接到字符串t4后
t4 += Character.toString(t1[i]);
}
}
} catch (Exception e) {
e.printStackTrace();
}
if (t4 != null && !"".equals(t4)) {
t4 = t4.toLowerCase();
}
}
return t4.toLowerCase();
}
}
MainApp
package view;
import java.io.*;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.prefs.Preferences;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import model.Person;
import model.PersonListWrapper;
public class MainApp extends Application {
private Stage primaryStage;//程序主页面
private BorderPane rootLayout;//背景页面、菜单
private ObservableList<Person> personData = FXCollections.observableArrayList();//运用一个集合类来存储每个联系人的数据
private List<String> personGroup = new ArrayList<>();//用一个list来存储分组数据
private String mainlygroup = " ";//当前选择的分组
private String searchNamestring ="";//当前想要查找的名字字符
private String searchPhonestring ="";//当前想要查找的电话号码字符
private boolean firststart = false;
public MainApp () {}
//将当前分组数据更新到分组list中
public void setPersonGroup(ObservableList<Person> personData){
for (Person person : personData) {
if(personGroup.isEmpty()&&!person.getgroupName().equals("None")){
personGroup.add(person.getgroupName());
}else{
if(!personGroup.contains(person.getgroupName())&&!person.getgroupName().equals("None")){
personGroup.add(person.getgroupName());
}
}
}
}
//清除分组数据
public void clearPersonGroup(){this.personGroup.clear();}
//添加分组
public void addPersonGroup(String groupName){this.personGroup.add(groupName);}
//删除分组
public void deletePersonGroup(String groupName){
for(Person person : rtPersonData()){
if(person.getgroupName().equals(groupName)){
person.setgroupName("None");
}
}
personGroup.clear();
setPersonGroup(rtPersonData());
}
//获得分组数据
public List<String> getPersonGroup(){return personGroup;}
//设置当前分组
public void setMainlygroup(String mainlygroup){this.mainlygroup = mainlygroup;}
//获取当前分组
public String getMainlygroup(){return mainlygroup;}
//获取当前程序中读取的联系人数据(副本)
public ObservableList<Person> getPersonData() {
if(mainlygroup.equals("all")&& searchNamestring.isEmpty() && searchPhonestring.isEmpty()){
return personData;
}
ObservableList<Person> personData1 = FXCollections.observableArrayList();
for(Person person : personData) {
if(searchNamestring.isEmpty() && searchPhonestring.isEmpty()){
if(person.getgroupName().equals(mainlygroup)) {
personData1.add(person);
}
}else if(searchPhonestring.isEmpty()){
if(cmp(ChangeHanziToPinyin.getPinYin(searchNamestring),ChangeHanziToPinyin.getPinYin(person.getPersonName()))){
personData1.add(person);
}
}else if(searchNamestring.isEmpty()){
if(cmp(searchPhonestring,person.getPhonenumber())){
personData1.add(person);
}
}else{
if(cmp(searchPhonestring,person.getPhonenumber())&&cmp(ChangeHanziToPinyin.getPinYin(searchNamestring),ChangeHanziToPinyin.getPinYin(person.getPersonName()))){
personData1.add(person);
}
}
}
return personData1;
}
//获取当前程序中读取的数据,可改变
public ObservableList<Person> rtPersonData(){return personData;}
//字符串对比方法,用于实现搜索功能
public boolean cmp(String searchstring, String thisname){
char [] arr = searchstring.toCharArray();
int res=0;
for(char ch : thisname.toCharArray()) {
for(char ch2 : arr) {
if(ch == ch2) {
++res;
}
}
}
if(res == 0){
return false;
}else {
return true;
}
}
//设置搜索名字
public void setSearchNamestring(String searchNamestring){this.searchNamestring = searchNamestring;}
//设置搜索电话号码
public void setSearchPhonestring(String searchPhonestring){this.searchPhonestring = searchPhonestring;}
//获取搜索名字
public String getSearchNamestring(){return searchNamestring;}
//程序启动
@Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("通讯录管理APP");
this.primaryStage.getIcons().add(new Image("File:src\\view\\app.png"));
//设置背景、菜单
initRootLayout();
//设置程序主界面
showPersonOverview();
}
//设置菜单和背景界面
public void initRootLayout() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("RootLayout.fxml"));//读取fxml文件,存储了可视化界面的代码
rootLayout = (BorderPane) loader.load();
if(!firststart) {
File file = getPersonFilePath();
if (file != null) {
if(file.getPath().endsWith(".xml")){
loadPersonDataFromFile(file);
}
else if(file.getPath().endsWith(".csv")){
loadPersonDataFromCSVFile(file);
}
else if(file.getPath().endsWith(".vcf")){
loadPersonDataFromvCardFile(file);
}
}
firststart = true;
}
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
RootLayoutController controller = loader.getController();
controller.setMainApp(this);
setPersonGroup(personData);//初始化组菜单
controller.initMenuItem(getPersonGroup());
primaryStage.show();//呈现在舞台中
} catch (IOException e) {
e.printStackTrace();
}
}
//设置用户主界面
public void showPersonOverview() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("PersonOverview.fxml"));
AnchorPane personOverview = (AnchorPane) loader.load();
rootLayout.setCenter(personOverview);//将该界面设置在背景的中心
PersonOverviewController controller = loader.getController();
controller.setMainApp(this);
} catch (IOException e) {
e.printStackTrace();
}
}
//呈现个人信息编辑界面
public boolean showPersonEditDialog(Person person) {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("PersonEditDialog.fxml"));
AnchorPane page = (AnchorPane) loader.load();
Stage dialogStage = new Stage();
dialogStage.setTitle("Edit Person");
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.initOwner(primaryStage);
Scene scene = new Scene(page);
dialogStage.setScene(scene);
PersonEditDialogController controller = loader.getController();
controller.setDialogStage(dialogStage);
controller.setPerson(person);
dialogStage.getIcons().add(new Image("file:src\\resources\\images\\edit.png"));
dialogStage.showAndWait();
return controller.isOkClicked();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
//呈现分组信息编辑界面
public boolean showPersonGroupEditDialog() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("PersonGroupEditDialog.fxml"));
AnchorPane page = (AnchorPane) loader.load();
Stage dialogStage = new Stage();
dialogStage.setTitle("New PersonGroup");
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.initOwner(primaryStage);
Scene scene = new Scene(page);
dialogStage.setScene(scene);
PersonGroupEditDialogController controller = loader.getController();
controller.setDialogStage(dialogStage);
controller.setMainApp(this);
dialogStage.getIcons().add(new Image("file:src\\resources\\images\\edit.png"));
dialogStage.showAndWait();
return controller.isOkClicked();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
//呈现分组信息删除界面
public boolean showPersonGroupDeleteDialog() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("PersonGroupDelete.fxml"));
AnchorPane page = (AnchorPane) loader.load();
Stage dialogStage = new Stage();
dialogStage.setTitle("Delete PersonGroup");
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.initOwner(primaryStage);
Scene scene = new Scene(page);
dialogStage.setScene(scene);
PersonGroupDeleteController controller = loader.getController();
controller.setDialogStage(dialogStage);
controller.setMainApp(this);
dialogStage.getIcons().add(new Image("file:src\\resources\\images\\edit.png"));
dialogStage.showAndWait();
return controller.isOkClicked();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
//呈现搜索界面
public boolean showPersonNameSearchDialog() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("PersonSearchDialog.fxml"));
AnchorPane page = (AnchorPane) loader.load();
Stage dialogStage = new Stage();
dialogStage.setTitle("Search Person");
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.initOwner(primaryStage);
Scene scene = new Scene(page);
dialogStage.setScene(scene);
PersonSearchDialogController controller = loader.getController();
controller.setDialogStage(dialogStage);
controller.setMainApp(this);
dialogStage.getIcons().add(new Image("file:src\\resources\\images\\edit.png"));
dialogStage.showAndWait();
return controller.isOkClicked();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
//获取文件地址(上一个)
public File getPersonFilePath() {
Preferences prefs = Preferences.userNodeForPackage(MainApp.class);
String filePath = prefs.get("filePath", null);
if (filePath != null) {
return new File(filePath);
} else {
return null;
}
}
//设置文件地址
public void setPersonFilePath(File file) {
Preferences prefs = Preferences.userNodeForPackage(MainApp.class);
if (file != null) {
prefs.put("filePath", file.getPath());
primaryStage.setTitle("*通讯录管理系统* - " + file.getName());
} else {
prefs.remove("filePath");
primaryStage.setTitle("*通讯录管理系统*");
}
}
//读取文件
public void loadPersonDataFromFile(File file) {
try {
JAXBContext context = JAXBContext.newInstance(PersonListWrapper.class);
Unmarshaller um = context.createUnmarshaller();
PersonListWrapper wrapper = (PersonListWrapper) um.unmarshal(file);
personData.clear();
personData.addAll(wrapper.getPersons());
setPersonGroup(personData);
setPersonFilePath(file);
} catch (Exception e) {
e.printStackTrace();
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText("Could not load data");
alert.setContentText("Could not load data from file:\n" + file.getPath());
alert.showAndWait();
}
}
//保存
public void savePersonDataToFile(File file) {
try {
JAXBContext context = JAXBContext
.newInstance(PersonListWrapper.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
PersonListWrapper wrapper = new PersonListWrapper();
wrapper.setPersons(personData);
m.marshal(wrapper, file);
setPersonFilePath(file);
} catch (Exception e) {
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText("Could not save data");
alert.setContentText("Could not save data to file:\n" + file.getPath());
alert.showAndWait();
}
}
//读取文件
public void loadPersonDataFromCSVFile(File csvFile) {
try {
BufferedReader reader = new BufferedReader(new FileReader(csvFile.getPath()));
personData.clear();
// 读取CSV文件内容
String line;
line = reader.readLine();
while ((line = reader.readLine()) != null) {
// 按逗号分割行内容
String[] fields = line.split(",");
Person person = new Person();
// 打印每一行的数据
int i=0;
for (String field : fields) {
switch (i){
case 0:
person.setgroupName(field);
break;
case 1:
person.setPersonName(field);
break;
case 2:
person.setEmailadd(field);
break;
case 3:
person.setBirthday(LocalDate.parse(field));
break;
case 4:
person.setHomeAddress(field);
break;
case 5:
person.setWorkAddress(field);
break;
case 6:
person.setPhonenumber(field);
break;
case 7:
person.setPostalCode(Integer.parseInt(field));
break;
case 8:
person.setExtralting(field);
break;
case 9:
person.setPersonimage(field);
break;
}
++i;
}
personData.add(person);
}
reader.close();
setPersonGroup(personData);
setPersonFilePath(csvFile);
// 关闭读取流
} catch (Exception e) {
e.printStackTrace();
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText("Could not load data");
alert.setContentText("Could not load data from file:\n" + csvFile.getPath());
alert.showAndWait();
}
}
//导出为CSV
public void creatCSV(File file){
try {
// 创建CSV文件写入流
FileWriter writer = new FileWriter(file);
// 写入CSV文件头部
writer.append("GroupName,PersonName,Email,Birthday,homeAddress,workAddress,phoneNumber,postalCode,extralting,personimage");
writer.append("\n");
// 写入数据
for(Person person : personData){
writer.append(person.getgroupName()).append(",").append(person.getPersonName()).append(",").append(person.getEmailadd()).append(",").append(person.getBirthday().toString()).append(",").append(person.getHomeAddress()).append(",").append(person.getWorkAddress()).append(",").append(person.getPhonenumber()).append(",").append(Integer.toString(person.getPostalCode())).append(",").append(person.getExtralting()).append(",").append(person.getPersonimage());
writer.append("\n");
}
// 关闭写入流
writer.flush();
writer.close();
System.out.println("CSV文件已创建成功!");
} catch (IOException e) {
System.out.println("创建CSV文件时出错:" + e.getMessage());
}
}
public void loadPersonDataFromvCardFile(File file) {
try {
BufferedReader reader = new BufferedReader(new FileReader(file.getPath()));
personData.clear();
// 读取vCard文件内容
String line;
int i=0;
Person person = new Person();
while ((line = reader.readLine()) != null) {
// 读取每一行的数据
if(i==0){
Person person1 = new Person();
person = person1;
}
String field = "";
if(i!=11){
String[] fields = line.split(":");
int j=0;
for(String f:fields){
++j;
if(j==2){
field = f;
break;
}
}
}else{
field = line.substring(6);
}
switch (i){
case 3:
person.setPersonName(field);
break;
case 4:
person.setgroupName(field);
break;
case 5:
person.setEmailadd(field);
break;
case 6:
person.setPhonenumber(field);
break;
case 7:
person.setBirthday(LocalDate.parse(field));
break;
case 8:
person.setHomeAddress(field);
break;
case 9:
person.setWorkAddress(field);
break;
case 10:
person.setExtralting(field);
break;
case 11:
person.setPersonimage(field);
break;
case 12:
person.setPostalCode(Integer.parseInt(field));
break;
}
++i;
if(i==13){
personData.add(person);
}
if(i==14){
i=0;
}
}
// 关闭读取流
reader.close();
setPersonGroup(personData);
setPersonFilePath(file);
} catch (Exception e) {
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText("Could not load data");
alert.setContentText("Could not load data from file:\n" + file.getPath());
alert.showAndWait();
}
}
//导出为vCard
public void creatvCard(File file){
try {
// 创建vCard文件写入流
FileWriter writer = new FileWriter(file);
// 写入示例vCard数据
for(Person person : personData){
writer.write("BEGIN:VCARD\n");
writer.write("VERSION:3.0\n");
writer.write("PRODID:ez-vcard 0.10.6");
writer.write("FN:"+person.getPersonName()+"\n");
writer.write("N:"+person.getPersonName()+"\n");
writer.write("GROUP:"+person.getgroupName()+"\n");
writer.write("EMAIL:"+person.getEmailadd()+"\n");
writer.write("TEL:"+person.getPhonenumber()+"\n");
writer.write("BDAY:"+person.getBirthday().toString()+"\n");
writer.write("ADR:"+person.getHomeAddress()+"\n");
writer.write("ADR:"+person.getWorkAddress()+"\n");
writer.write("NOTE:"+person.getExtralting()+"\n");
writer.write("PHOTO:"+person.getPersonimage()+"\n");
writer.write("POST:"+person.getPostalCode()+"\n");
writer.write("END:VCARD\n");
}
// 关闭写入流
writer.flush();
writer.close();
System.out.println("vCard文件已创建成功!");
} catch (IOException e) {
System.out.println("创建vCard文件时出错:" + e.getMessage());
}
}
public Stage getPrimaryStage() {
return primaryStage;
}
public static void main(String[] args) {
launch(args);
}
}
PersonEditDialog.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="410.0" prefWidth="520.0" styleClass="background" stylesheets="" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.PersonEditDialogController">
<children>
<GridPane layoutX="10.0" layoutY="44.0" prefHeight="296.0" prefWidth="419.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="44.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="218.0" minWidth="10.0" prefWidth="111.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="316.0" minWidth="10.0" prefWidth="261.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label text="组别" />
<Label text="姓名" GridPane.rowIndex="1" />
<Label text="家庭地址" GridPane.rowIndex="2" />
<Label text="工作单位" GridPane.rowIndex="3" />
<Label text="邮编" GridPane.rowIndex="4" />
<TextField fx:id="groupNameField" GridPane.columnIndex="1" />
<TextField fx:id="personNameField" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<TextField GridPane.columnIndex="1" GridPane.rowIndex="2" />
<TextField fx:id="homeAddressField" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<TextField fx:id="workAddressField" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<TextField fx:id="postalCodeField" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<TextField fx:id="birthdayField" GridPane.columnIndex="1" GridPane.rowIndex="5" />
<Label text="生日" GridPane.rowIndex="5" />
<Label text="电话号码" GridPane.rowIndex="6" />
<Label text="邮箱" GridPane.rowIndex="7" />
<Label text="备注" GridPane.rowIndex="8" />
<TextField fx:id="phonenumberField" GridPane.columnIndex="1" GridPane.rowIndex="6" />
<TextField fx:id="emailaddField" GridPane.columnIndex="1" GridPane.rowIndex="7" />
<TextField fx:id="extralingField" GridPane.columnIndex="1" GridPane.rowIndex="8" />
</children>
</GridPane>
<ButtonBar layoutX="176.0" layoutY="233.0" AnchorPane.bottomAnchor="10.0" AnchorPane.rightAnchor="10.0">
<buttons>
<Button defaultButton="true" mnemonicParsing="false" onAction="#handleOk" text="OK" />
<Button mnemonicParsing="false" onAction="#handleCancel" prefWidth="120.0" text="Cancel" />
</buttons>
</ButtonBar>
</children>
</AnchorPane>
PersonEditDialogController
package view;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import model.Person;
import util.DateUtil;
public class PersonEditDialogController {
@FXML
private TextField groupNameField;
@FXML
private TextField personNameField;
@FXML
private TextField homeAddressField;
@FXML
private TextField postalCodeField;
@FXML
private TextField workAddressField;
@FXML
private TextField birthdayField;
@FXML
private TextField phonenumberField;
@FXML
private TextField emailaddField;
@FXML
private TextField extralingField;
private Stage dialogStage;
private Person person;
private boolean okClicked = false;
@FXML
private void initialize() {
}
//设置舞台
public void setDialogStage(Stage dialogStage) {
this.dialogStage = dialogStage;
this.dialogStage.getIcons().add(new Image("file:src\\resources\\images\\edit.png"));
}
//将原本的信息呈现在编辑框中
public void setPerson(Person person) {
this.person = person;
groupNameField.setText(person.getgroupName());
personNameField.setText(person.getPersonName());
homeAddressField.setText(person.getHomeAddress());
postalCodeField.setText(Integer.toString(person.getPostalCode()));
workAddressField.setText(person.getWorkAddress());
birthdayField.setText(DateUtil.format(person.getBirthday()));
birthdayField.setPromptText("dd.mm.yyyy");
phonenumberField.setText(person.getPhonenumber());
emailaddField.setText(person.getEmailadd());
extralingField.setText(person.getExtralting());
}
//判断是否点击确定
public boolean isOkClicked() {
return okClicked;
}
//OK按钮事件
@FXML
private void handleOk() {
if (isInputValid()) {
person.setgroupName(groupNameField.getText());
person.setPersonName(personNameField.getText());
person.setHomeAddress(homeAddressField.getText());
person.setPostalCode(Integer.parseInt(postalCodeField.getText()));
person.setWorkAddress(workAddressField.getText());
person.setBirthday(DateUtil.parse(birthdayField.getText()));
person.setPhonenumber(phonenumberField.getText());
person.setEmailadd(emailaddField.getText());
person.setExtralting(extralingField.getText());
okClicked = true;
dialogStage.close();
}
}
//取消按钮事件
@FXML
private void handleCancel() {
dialogStage.close();
}
//是否输入
private boolean isInputValid() {
String errorMessage = "";
if (groupNameField.getText() == null || groupNameField.getText().length() == 0) {
errorMessage += "No valid group name!\n";
}
if (personNameField.getText() == null || personNameField.getText().length() == 0) {
errorMessage += "No valid person name!\n";
}
if (homeAddressField.getText() == null || homeAddressField.getText().length() == 0) {
errorMessage += "No valid home address!\n";
}
if (postalCodeField.getText() == null || postalCodeField.getText().length() == 0) {
errorMessage += "No valid postal code!\n";
}
if (phonenumberField.getText() == null || phonenumberField.getText().length() == 0) {
errorMessage += "No valid phone number!\n";
}
if (emailaddField.getText() == null || emailaddField.getText().length() == 0) {
errorMessage += "No valid email address!\n";
}
if (extralingField.getText() == null || extralingField.getText().length() == 0) {
errorMessage += "No valid extral word!\n";
}else {
try {
Integer.parseInt(postalCodeField.getText());
} catch (NumberFormatException e) {
errorMessage += "No valid postal code (must be an integer)!\n";
}
}
if (workAddressField.getText() == null || workAddressField.getText().length() == 0) {
errorMessage += "No valid work address!\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 yyyy.mm.dd!\n";
}
}
if (errorMessage.length() == 0) {
return true;
} else {
Alert alert = new Alert(AlertType.ERROR);
alert.initOwner(dialogStage);
alert.setTitle("Invalid Fields");
alert.setHeaderText("Please correct invalid fields");
alert.setContentText(errorMessage);
alert.showAndWait();
return false;
}
}
}
PersonGroupDelete.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.PersonGroupDeleteController">
<children>
<GridPane layoutX="123.0" layoutY="155.0" prefHeight="53.0" prefWidth="349.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label prefHeight="36.0" prefWidth="108.0" text="需要删除的分组:" />
<TextField fx:id="groupNameField" prefHeight="43.0" prefWidth="174.0" GridPane.columnIndex="1" />
</children>
</GridPane>
<Button layoutX="150.0" layoutY="295.0" mnemonicParsing="false" onAction="#handleOk" prefHeight="53.0" prefWidth="120.0" text="确定" />
<Button layoutX="309.0" layoutY="295.0" mnemonicParsing="false" onAction="#handleCancel" prefHeight="53.0" prefWidth="120.0" text="取消" />
</children>
</AnchorPane>
PersonGroupDeleteController
package view;
import java.io.File;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import model.Person;
public class PersonGroupDeleteController {
@FXML
private TextField groupNameField;
private Stage groupdialogStage;
private String groupName;
private MainApp mainApp;
private boolean okClicked = false;
@FXML
private void initialize() {
}
//设置舞台
public void setDialogStage(Stage dialogStage) {
this.groupdialogStage = dialogStage;
this.groupdialogStage.getIcons().add(new Image("file:src\\resources\\images\\edit.png"));
}
//设置组名
public void setGroupName(String groupName) {this.groupName = groupName;}
//将mainAPP传入,用于调用一些方法以及修改变量
public void setMainApp(MainApp mainApp) {this.mainApp = mainApp;}
//返回是否按下确定按钮
public boolean isOkClicked() {
return okClicked;
}
//确定按钮事件
@FXML
private void handleOk() {
if (isInputValid()) {
mainApp.deletePersonGroup(groupNameField.getText());
okClicked = true;
groupdialogStage.close();
}
}
//取消按钮事件
@FXML
private void handleCancel() {
groupdialogStage.close();
}
//判断输入合法性
private boolean isInputValid() {
String errorMessage = "";
if (groupNameField.getText().isEmpty()) {
errorMessage += "No valid group name!\n";
}
if (errorMessage.length()==0) {
return true;
} else {
// Show the error message.
Alert alert = new Alert(AlertType.ERROR);
alert.initOwner(groupdialogStage);
alert.setTitle("Invalid Fields");
alert.setHeaderText("Please correct invalid fields");
alert.setContentText(errorMessage);
alert.showAndWait();
return false;
}
}
}
PersonGroupEditDialog.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane prefHeight="212.0" prefWidth="445.0" styleClass="background" stylesheets="" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.PersonGroupEditDialogController">
<children>
<GridPane layoutX="40.0" layoutY="36.0" prefHeight="66.0" prefWidth="368.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="186.0" minWidth="10.0" prefWidth="103.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="265.0" minWidth="10.0" prefWidth="265.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label prefHeight="44.0" prefWidth="93.0" styleClass="label-bright" stylesheets="" text="新增分组" />
<TextField fx:id="groupNameField" prefHeight="66.0" prefWidth="211.0" GridPane.columnIndex="1" />
</children>
</GridPane>
<Button layoutX="99.0" layoutY="147.0" mnemonicParsing="false" onAction="#handleOk" text="确定" />
<Button layoutX="254.0" layoutY="147.0" mnemonicParsing="false" onAction="#handleCancel" text="取消" />
</children>
</AnchorPane>
PersonGroupEditDialogController
package view;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.stage.Stage;
public class PersonGroupEditDialogController {
@FXML
private TextField groupNameField;
private Stage groupdialogStage;
private String groupName;
private MainApp mainApp;
private boolean okClicked = false;
@FXML
private void initialize() {
}
//设置舞台
public void setDialogStage(Stage dialogStage) {
this.groupdialogStage = dialogStage;
this.groupdialogStage.getIcons().add(new Image("file:src\\resources\\images\\edit.png"));
}
//设置组名
public void setGroupName(String groupName) {this.groupName = groupName;}
//将mainAPP传入,用于调用一些方法以及修改变量
public void setMainApp(MainApp mainApp) {this.mainApp = mainApp;}
//返回是否按下确定按钮
public boolean isOkClicked() {
return okClicked;
}
//确定按钮事件
@FXML
private void handleOk() {
if (isInputValid()) {
mainApp.addPersonGroup(groupNameField.getText());
okClicked = true;
groupdialogStage.close();
}
}
//取消按钮事件
@FXML
private void handleCancel() {
groupdialogStage.close();
}
//判断输入合法性
private boolean isInputValid() {
String errorMessage = "";
if (groupNameField.getText() == null || groupNameField.getText().length() == 0) {
errorMessage += "No valid group name!\n";
}
if (errorMessage.length() == 0) {
return true;
} else {
// Show the error message.
Alert alert = new Alert(AlertType.ERROR);
alert.initOwner(groupdialogStage);
alert.setTitle("Invalid Fields");
alert.setHeaderText("Please correct invalid fields");
alert.setContentText(errorMessage);
alert.showAndWait();
return false;
}
}
}
PersonOverview.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="900.0" prefWidth="1500.0" stylesheets="" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.PersonOverviewController">
<children>
<SplitPane dividerPositions="0.4126984126984127" layoutX="153.0" layoutY="70.0" prefHeight="300.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<TableView fx:id="personTable" layoutX="-12.0" layoutY="49.0" prefHeight="298.0" prefWidth="175.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columns>
<TableColumn fx:id="groupColumn" prefWidth="75.0" text="组别" />
<TableColumn fx:id="personNameColumn" prefWidth="75.0" text="姓名" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="900.0" prefWidth="1500.0" styleClass="background">
<children>
<Label layoutX="33.0" layoutY="8.0" prefHeight="34.0" prefWidth="266.0" styleClass="label-header" text="Person Details" AnchorPane.leftAnchor="33.0" AnchorPane.topAnchor="8.0" />
<GridPane layoutX="14.0" layoutY="293.0" prefHeight="313.0" prefWidth="867.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="-4.0" AnchorPane.topAnchor="293.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="196.0" minWidth="10.0" prefWidth="142.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="251.0" minWidth="10.0" prefWidth="251.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="26.0" minHeight="10.0" prefHeight="26.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="36.0" minHeight="10.0" prefHeight="31.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="34.0" minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="39.0" minHeight="10.0" prefHeight="29.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="40.0" minHeight="10.0" prefHeight="33.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="44.0" minHeight="10.0" prefHeight="37.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="48.0" minHeight="20.0" prefHeight="41.0" />
<RowConstraints maxHeight="41.0" minHeight="6.0" prefHeight="32.0" />
<RowConstraints maxHeight="42.0" minHeight="7.0" prefHeight="42.0" />
</rowConstraints>
<children>
<Label text="组别" />
<Label text="姓名" GridPane.rowIndex="1" />
<Label text="家庭地址" GridPane.rowIndex="2" />
<Label text="工作单位" GridPane.rowIndex="3" />
<Label text="邮编" GridPane.rowIndex="4" />
<Label text="生日" GridPane.rowIndex="5" />
<Label text="电话" GridPane.rowIndex="6" />
<Label text="邮箱" GridPane.rowIndex="7" />
<Label text="备注" GridPane.rowIndex="8" />
<Label fx:id="groupNameLabel" styleClass="label-bright" text="Label" GridPane.columnIndex="1" />
<Label fx:id="personNameLabel" styleClass="label-bright" text="Label" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Label fx:id="streetLabel" styleClass="label-bright" text="Label" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Label fx:id="cityLabel" styleClass="label-bright" text="Label" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<Label fx:id="postalCodeLabel" styleClass="label-bright" text="Label" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<Label fx:id="birthdayLabel" styleClass="label-bright" text="Label" GridPane.columnIndex="1" GridPane.rowIndex="5" />
<Label fx:id="phonenumberLabel" prefHeight="21.0" prefWidth="179.0" styleClass="label-bright" text="111" GridPane.columnIndex="1" GridPane.rowIndex="6" />
<Label fx:id="emailaddLabel" prefHeight="21.0" prefWidth="215.0" styleClass="label-bright" text="222" GridPane.columnIndex="1" GridPane.rowIndex="7" />
<Label fx:id="extraltingLabel" prefHeight="21.0" prefWidth="193.0" styleClass="label-bright" text="333" GridPane.columnIndex="1" GridPane.rowIndex="8" />
</children>
</GridPane>
<ButtonBar layoutX="54.0" layoutY="250.0" AnchorPane.bottomAnchor="10.0" AnchorPane.rightAnchor="10.0">
<buttons>
<Button mnemonicParsing="false" onAction="#handleNewPerson" text="New..." />
<Button mnemonicParsing="false" onAction="#handleEditPerson" text="Edit..." />
<Button mnemonicParsing="false" onAction="#handleDeletePerson" text="Delete" />
<Button mnemonicParsing="false" onAction="#handleSearchPerson" text="Search" />
<Button mnemonicParsing="false" onAction="#handleResetSearch" text="ResetSearch" />
<Button mnemonicParsing="false" onAction="#handleEditImage" text="EditImage" />
</buttons>
</ButtonBar>
<ImageView fx:id="personImage" fitHeight="179.0" fitWidth="266.0" layoutX="47.0" layoutY="89.0" pickOnBounds="true" preserveRatio="true" />
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
PersonOverviewController
package view;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.FileChooser;
import model.Person;
import util.DateUtil;
import java.io.File;
public class PersonOverviewController {
private String group;//用于分组
@FXML
private TableView<Person> personTable;
@FXML
private TableColumn<Person, String> groupColumn;
@FXML
private TableColumn<Person, String> personNameColumn;
@FXML
private ImageView personImage;
@FXML
private Label groupNameLabel;
@FXML
private Label personNameLabel;
@FXML
private Label streetLabel;
@FXML
private Label postalCodeLabel;
@FXML
private Label cityLabel;
@FXML
private Label birthdayLabel;
@FXML
private Label phonenumberLabel;
@FXML
private Label emailaddLabel;
@FXML
private Label extraltingLabel;
private MainApp mainApp;
public String getGroup() {return group;}
public void setGroup(String group) {this.group = group;}
//设置组为所有(默认)
public PersonOverviewController() {
this.group="all";
}
//用户界面初始化
@FXML
private void initialize() {
groupColumn.setCellValueFactory(cellData -> cellData.getValue().groupNameProperty());
personNameColumn.setCellValueFactory(cellData -> cellData.getValue().personNameProperty());
showPersonDetails(null);
personTable.getSelectionModel().selectedItemProperty().addListener(
(observable, oldValue, newValue) -> showPersonDetails(newValue));
}
//传入mainapp,用于刷新以及初始化
public void setMainApp(MainApp mainApp) {
this.mainApp = mainApp;
personTable.setItems(mainApp.getPersonData());
}
//当选择表中的联系人时,将联系人的信息呈现在个人主页中
private void showPersonDetails(Person person) {
if(person != null) {
groupNameLabel.setText(person.getgroupName());
personNameLabel.setText(person.getPersonName());
streetLabel.setText(person.getHomeAddress());
postalCodeLabel.setText(Integer.toString(person.getPostalCode()));
cityLabel.setText(person.getWorkAddress());
birthdayLabel.setText(DateUtil.format(person.getBirthday()));
phonenumberLabel.setText(person.getPhonenumber());
emailaddLabel.setText(person.getEmailadd());
extraltingLabel.setText(person.getExtralting());
Image image = new Image(person.getPersonimage());
personImage.setImage(image);
}else {
groupNameLabel.setText("");
personNameLabel.setText("");
streetLabel.setText("");
postalCodeLabel.setText("");
cityLabel.setText("");
birthdayLabel.setText("");
phonenumberLabel.setText("");
emailaddLabel.setText("");
extraltingLabel.setText("");
}
}
//删除按钮事件
@FXML
private void handleDeletePerson() {
int selectedIndex = personTable.getSelectionModel().getSelectedIndex();//用于判断是否选择了一个联系人
if (selectedIndex >= 0) {
mainApp.rtPersonData().remove(selectedIndex);
personTable.getItems().remove(selectedIndex);
} else {
Alert alert = new Alert(AlertType.WARNING);
alert.initOwner(mainApp.getPrimaryStage());
alert.setTitle("No Selection");
alert.setHeaderText("No Person Selected");
alert.setContentText("Please select a person in the table.");
alert.showAndWait();
}
}
//新增联系人按钮事件
@FXML
private void handleNewPerson() {
Person tempPerson = new Person();
boolean okClicked = mainApp.showPersonEditDialog(tempPerson);//判断是否按下确定
if (okClicked) {
mainApp.rtPersonData().add(tempPerson);
mainApp.setPersonGroup(mainApp.getPersonData());
mainApp.showPersonOverview();
}
}
//搜索按钮事件
@FXML
private void handleSearchPerson() {
boolean okClicked = mainApp.showPersonNameSearchDialog();
if (okClicked) {
mainApp.showPersonOverview();
}
}
//搜索功能复位案件事件
@FXML
private void handleResetSearch() {
mainApp.setSearchNamestring("");
mainApp.setSearchPhonestring("");
mainApp.showPersonOverview();
}
//编辑功能按钮事件
@FXML
private void handleEditPerson() {
Person selectedPerson = personTable.getSelectionModel().getSelectedItem();
if (selectedPerson != null) {
boolean okClicked = mainApp.showPersonEditDialog(selectedPerson);
if (okClicked) {
mainApp.setPersonGroup(mainApp.getPersonData());
mainApp.showPersonOverview();
}
} else {
Alert alert = new Alert(AlertType.WARNING);
alert.initOwner(mainApp.getPrimaryStage());
alert.setTitle("No Selection");
alert.setHeaderText("No Person Selected");
alert.setContentText("Please select a person in the table.");
alert.showAndWait();
}
}
//编辑图片按钮事件
@FXML
private void handleEditImage() {
Person selectedPerson = personTable.getSelectionModel().getSelectedItem();
if (selectedPerson != null) {
FileChooser fileChooser = new FileChooser();
FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("PNG files", "*.png");
FileChooser.ExtensionFilter extFilter1 = new FileChooser.ExtensionFilter("JPG files", "*.jpg");
FileChooser.ExtensionFilter extFilter2 = new FileChooser.ExtensionFilter("JPEG files", "*.jpeg");
fileChooser.getExtensionFilters().add(extFilter);
fileChooser.getExtensionFilters().add(extFilter1);
fileChooser.getExtensionFilters().add(extFilter2);
File file = fileChooser.showOpenDialog(mainApp.getPrimaryStage());
String s = file.toURI().toString();
selectedPerson.setPersonimage(s);
mainApp.showPersonOverview();
showPersonDetails(selectedPerson);
} else {
Alert alert = new Alert(AlertType.WARNING);
alert.initOwner(mainApp.getPrimaryStage());
alert.setTitle("No Selection");
alert.setHeaderText("No Person Selected");
alert.setContentText("Please select a person in the table.");
alert.showAndWait();
}
}
}
PersonSearchDialog.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane prefHeight="238.0" prefWidth="442.0" styleClass="background" stylesheets="" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.PersonSearchDialogController">
<children>
<GridPane layoutX="50.0" layoutY="35.0" prefHeight="101.0" prefWidth="334.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="162.0" minWidth="10.0" prefWidth="102.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="232.0" minWidth="10.0" prefWidth="232.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label prefHeight="21.0" prefWidth="86.0" styleClass="label-bright" stylesheets="" text="名字:" />
<TextField fx:id="searchNameTextField" GridPane.columnIndex="1" />
<Label text="电话号码:" GridPane.rowIndex="1" />
<TextField fx:id="searchNumTextField1" GridPane.columnIndex="1" GridPane.rowIndex="1" />
</children>
</GridPane>
<Button layoutX="109.0" layoutY="163.0" mnemonicParsing="false" onAction="#handleOk" prefHeight="23.0" prefWidth="78.0" text="确定" />
<Button layoutX="248.0" layoutY="163.0" mnemonicParsing="false" onAction="#handleCancel" prefHeight="23.0" prefWidth="78.0" text="取消" />
</children>
</AnchorPane>
PersonSearchDialogController
package view;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.stage.Stage;
public class PersonSearchDialogController {
@FXML
private TextField searchNameTextField;
@FXML
private TextField searchNumTextField1;
private Stage groupdialogStage;
private String personName;
private MainApp mainApp;
private boolean okClicked = false;
@FXML
private void initialize() {
}
public void setDialogStage(Stage dialogStage) {
this.groupdialogStage = dialogStage;
this.groupdialogStage.getIcons().add(new Image("file:src\\resources\\images\\edit.png"));
}
public void setPersonName(String personName) {this.personName = personName;}
public void setMainApp(MainApp mainApp) {this.mainApp = mainApp;}
public boolean isOkClicked() {
return okClicked;
}
//确定按钮事件,按下后调用mainapp中的搜索方法
@FXML
private void handleOk() {
if (isInputValid()) {
mainApp.setSearchNamestring(searchNameTextField.getText());
mainApp.setSearchPhonestring(searchNumTextField1.getText());
okClicked = true;
groupdialogStage.close();
}
}
@FXML
private void handleCancel() {
groupdialogStage.close();
}
private boolean isInputValid() {
String errorMessage = "";
if (searchNameTextField.getText() == null && searchNumTextField1.getText() == null) {
errorMessage += "No input!";
}
if (errorMessage.length() == 0) {
return true;
} else {
Alert alert = new Alert(AlertType.ERROR);
alert.initOwner(groupdialogStage);
alert.setTitle("Invalid Fields");
alert.setHeaderText("Please correct invalid fields");
alert.setContentText(errorMessage);
alert.showAndWait();
return false;
}
}
}
RootLayout.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.input.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane prefHeight="1000.0" prefWidth="1600.0" stylesheets="" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.RootLayoutController">
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" onAction="#handleNew" text="New">
<accelerator>
<KeyCodeCombination alt="UP" code="N" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
</accelerator>
</MenuItem>
<MenuItem mnemonicParsing="false" onAction="#handleSave" text="Save">
<accelerator>
<KeyCodeCombination alt="UP" code="S" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
</accelerator>
</MenuItem>
<MenuItem mnemonicParsing="false" onAction="#handleOpenXML" text="OpenXML">
</MenuItem>
<MenuItem mnemonicParsing="false" onAction="#handleOpenCSV" text="OpenCSV"/>
<MenuItem mnemonicParsing="false" onAction="#handleOpenvCard" text="OpenvCard"/>
<MenuItem mnemonicParsing="false" onAction="#handleSaveAs" text="Save AsXML" />
<MenuItem mnemonicParsing="false" onAction="#handleSaveAsCSV" text="Save AsCSV" />
<MenuItem mnemonicParsing="false" onAction="#handleSaveASvCard" text="Save AsvCard" />
<MenuItem mnemonicParsing="false" onAction="#handleExit" text="Exit" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" onAction="#handleAbout" text="About" />
</items>
</Menu>
<Menu fx:id="Group" mnemonicParsing="false" text="Group">
<items>
<MenuItem fx:id="Newgroup" mnemonicParsing="false" onAction="#handleNewgroup" text="NewGroup" />
<MenuItem fx:id="Deleteroup" mnemonicParsing="false" onAction="#handleDeletegroup" text="DeleteGroup" />
<MenuItem fx:id="ALlgroup" mnemonicParsing="false" onAction="#handleAllgroup" text="ALL" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
</BorderPane>
RootLayoutController
package view;
import java.io.File;
import java.util.List;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.CheckMenuItem;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.stage.FileChooser;
import model.Person;
public class RootLayoutController {
private MainApp mainApp;
@FXML
private Menu Group;
@FXML
private MenuItem Newgroup;
@FXML
private MenuItem ALlgroup;
public void setMainApp(MainApp mainApp) {
this.mainApp = mainApp;
}
public void initMenuItem(List<String> personGroup){
for(String group : personGroup){
MenuItem item = new MenuItem(group);
item.setOnAction(event -> {
MenuItemaction(group);
});
Group.getItems().add(item);
}
}
public void MenuItemaction(String group){
mainApp.setMainlygroup(group);
mainApp.showPersonOverview();
}
@FXML
private void handleNew() {
String group = "null";
mainApp.getPersonData().clear();//清空联系人数据
mainApp.clearPersonGroup();//新建一个文件后清空分组数据
mainApp.setPersonFilePath(null);
mainApp.initRootLayout();
mainApp.showPersonOverview();
}
@FXML
private void handleOpenXML() {
FileChooser fileChooser = new FileChooser();
//设置打开的文件的后缀
FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("XML files (*.xml)", "*.xml");
fileChooser.getExtensionFilters().add(extFilter);
File file = fileChooser.showOpenDialog(mainApp.getPrimaryStage());
if (file != null) {
mainApp.loadPersonDataFromFile(file);
mainApp.initRootLayout();
mainApp.showPersonOverview();
}
}
@FXML
private void handleOpenCSV() {
FileChooser fileChooser = new FileChooser();
//设置打开的文件的后缀
FileChooser.ExtensionFilter extFilter1 = new FileChooser.ExtensionFilter("CSV files (*.CSV)", "*.CSV");
fileChooser.getExtensionFilters().add(extFilter1);
File file = fileChooser.showOpenDialog(mainApp.getPrimaryStage());
if (file != null) {
mainApp.loadPersonDataFromCSVFile(file);
mainApp.initRootLayout();
mainApp.showPersonOverview();
}
}
@FXML
private void handleOpenvCard() {
FileChooser fileChooser = new FileChooser();
//设置打开的文件的后缀
FileChooser.ExtensionFilter extFilter2 = new FileChooser.ExtensionFilter("vCard files (*.vcf)", "*.vcf");
fileChooser.getExtensionFilters().add(extFilter2);
File file = fileChooser.showOpenDialog(mainApp.getPrimaryStage());
if (file != null) {
mainApp.loadPersonDataFromvCardFile(file);
mainApp.initRootLayout();
mainApp.showPersonOverview();
}
}
@FXML
private void handleSave() {
File personFile = mainApp.getPersonFilePath();
if (personFile != null) {
mainApp.savePersonDataToFile(personFile);
} else {
handleSaveAs();
}
}
//导出为csv
@FXML
private void handleSaveAsCSV() {
FileChooser fileChooser = new FileChooser();
FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("CSV files", "*.csv");
fileChooser.getExtensionFilters().add(extFilter);
File file = fileChooser.showSaveDialog(mainApp.getPrimaryStage());
if (file != null) {
if (!file.getPath().endsWith(".csv")) {
file = new File(file.getPath() + ".csv");
}
mainApp.creatCSV(file);
}
}
//导出为vcard
@FXML
private void handleSaveASvCard() {
FileChooser fileChooser = new FileChooser();
FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("vCard files", "*.vcf");
fileChooser.getExtensionFilters().add(extFilter);
File file = fileChooser.showSaveDialog(mainApp.getPrimaryStage());
if (file != null) {
if (!file.getPath().endsWith(".vcf")) {
file = new File(file.getPath() + ".vcf");
}
mainApp.creatvCard(file);
}
}
//另存为xml
@FXML
private void handleSaveAs() {
FileChooser fileChooser = new FileChooser();
FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("XML files (*.xml)", "*.xml");
fileChooser.getExtensionFilters().add(extFilter);
File file = fileChooser.showSaveDialog(mainApp.getPrimaryStage());
if (file != null) {
if (!file.getPath().endsWith(".xml")) {
file = new File(file.getPath() + ".xml");
}
mainApp.savePersonDataToFile(file);
}
}
@FXML
private void handleAbout() {
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("*通讯录管理系统*");
alert.setHeaderText("About");
alert.setContentText("Made by mika.");
alert.showAndWait();
}
@FXML
private void handleAllgroup() {
mainApp.setMainlygroup("all");
mainApp.showPersonOverview();
}
@FXML
private void handleNewgroup() {
boolean okClicked = mainApp.showPersonGroupEditDialog();
if (okClicked) {
mainApp.initRootLayout();
mainApp.showPersonOverview();
}
}
@FXML
private void handleDeletegroup() {
boolean okClicked = mainApp.showPersonGroupDeleteDialog();
if (okClicked) {
mainApp.initRootLayout();
mainApp.showPersonOverview();
}
}
@FXML
private void handleExit() {
System.exit(0);
}
}