基于java的通讯录管理系统(含基于javafx的可视化界面)

这是一个基于Java的通讯录管理系统,利用JavaFX构建可视化界面。功能包括分组管理、个人信息增删改查、模糊搜索及多种文件格式的导入导出。开发环境为IntelliJ IDEA,使用JavaFX Scene Builder设计界面,依赖pinyin4j和ez-vcard库。项目提供了详细的类图和代码结构。

项目简介:

基于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

项目结构:

699b162a6e3245b6a40d3159b1cc9ae5.png

项目类图:

17fc4ec6c5564ac5b10ea8fd109c02b4.png

项目代码:

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);
实现了以下要求说明的功能: 1.要求使用GUI,采用 Swing 技术数据存储采用文件系统(可以是文本 文件、xml 文件、vCard 文件或其他自定义格式文件,但不能是 Excel 文件)。不 使用数据库。 2. 通讯录中每个项目包括: ( 1)基本信息:姓名、手机号码、电子邮箱、生日、所属组、备注、像片。 ( 2)工作单位:国家、省份、城市、地址、工作单位、所属部门、职位、 邮编、电话、传真 ( 3)网络信息:个人主页、即时通信工具及号码、备用邮箱 ( 4)家庭资料:国家、省份、城市、地址、邮编、电话 3 .通讯录数据的录入功能:输入并存储新的通讯录数据,输入时如果有同 名或同电话号码时,应该给出提示。 4 .通讯录数据的查询功能: ( 1)默认列出所有条目。 ( 2)模糊查询,可以按:姓名、电话号码、手机、姓名的汉语拼音的声母 或全拼查询。支持模糊查询即输入部分数据后,可以查询出符合条件的全部条目。 如:输入“张”,列出所有名字中有“张”的条目;输入“ 2645”列出电话中有 该 4个数字的所有条目;输入“xl ”,列出声母为该 2 个字母的所有条目 ( 3)指定分组后,列出某分组的所有条目 说明:查询结果如果有多个条目,应按照姓名排序,并使用姓或姓的第一 个汉语拼音的字母分类。 5 .删除和修改功能:查询到一个条目后,可以删除该条目或修改条目内容。 6 .通信录内容的导入和导出功能。要求能够以CSV 格式和 vCard 格式导入 和导出通讯录的全部内容。并能够与主流手机或其他通讯录软件交换数据。 7 .通讯录显示设置,可以设置在显示查询结果时,一个条目可以显示或不 显示哪些内容。 注意:本系统实现了读取和保存csv文件,同时csv文件中只保存了图片的路径。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YoloMari

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值