Qt个人通讯录项目开发教程 - 从零开始构建联系人管理系统

Qt个人通讯录项目开发教程 - 从零开始构建联系人管理系统

项目概述

本项目是一个基于Qt框架开发的个人通讯录管理系统,具有完整的联系人CRUD操作、搜索功能和数据导入导出功能。项目采用C++语言开发,使用Qt的SQL模块实现数据持久化,通过MVC架构模式实现界面与数据的分离。

项目特点:

  • 📱 现代化界面设计,操作简洁直观
  • 💾 SQLite数据库存储,数据安全可靠
  • 🔍 多字段模糊搜索功能
  • 📤 支持CSV格式数据导入导出
  • ✅ 完整的数据验证机制
  • 🎯 MVC架构设计,代码结构清晰
  • 📋 详情面板实时显示联系人信息

源代码下载: https://download.csdn.net/download/weixin_42059464/91707072

技术栈

  • 开发语言: C++
  • GUI框架: Qt 5/6
  • 数据库: SQLite
  • 开发工具: Qt Creator
  • 编译器: 支持C++11及以上版本
  • 操作系统: 跨平台(Windows、macOS、Linux)

项目结构

复制代码
10_PersonalContactList/
├── 10_PersonalContactList.pro    # Qt项目配置文件
├── main.cpp                      # 程序入口文件
├── mainwindow.h                  # 主窗口类头文件
├── mainwindow.cpp                # 主窗口类实现文件
├── mainwindow.ui                 # 主窗口UI设计文件
├── contactdialog.h               # 联系人对话框头文件
└── contactdialog.cpp             # 联系人对话框实现文件

核心功能实现

1. 界面设计

1.1 主窗口布局

主窗口采用分割布局设计,左侧为联系人列表,右侧为详情面板:

cpp 复制代码
// 主窗口布局结构
class MainWindow : public QMainWindow
{
    Q_OBJECT

private:
    Ui::MainWindow *ui;           // UI界面对象
    ContactDialog *contactDialog; // 联系人编辑对话框
    QSqlDatabase db;              // 数据库连接
    QSqlTableModel *contactModel; // 数据模型
};
1.2 联系人对话框设计

联系人编辑对话框采用表单布局,包含完整的联系人信息输入字段:

cpp 复制代码
void ContactDialog::setupUI()
{
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    
    // 创建表单组
    QGroupBox *formGroup = new QGroupBox("联系人信息");
    QGridLayout *formLayout = new QGridLayout(formGroup);
    
    // 姓名输入框
    QLabel *nameLabel = new QLabel("姓名:");
    nameEdit = new QLineEdit;
    nameEdit->setPlaceholderText("请输入姓名");
    formLayout->addWidget(nameLabel, 0, 0);
    formLayout->addWidget(nameEdit, 0, 1);
    
    // 电话号码输入框(带验证器)
    QLabel *phoneLabel = new QLabel("电话号码:");
    phoneEdit = new QLineEdit;
    phoneEdit->setPlaceholderText("请输入电话号码");
    QRegExp phoneRegex("^[0-9\\-\\+\\s\\(\\)]{0,20}$");
    phoneEdit->setValidator(new QRegExpValidator(phoneRegex, this));
    formLayout->addWidget(phoneLabel, 1, 0);
    formLayout->addWidget(phoneEdit, 1, 1);
}
1.3 数据验证机制

为电话号码和邮箱地址添加格式验证:

cpp 复制代码
// 电话号码验证
bool MainWindow::isValidPhoneNumber(const QString &phone)
{
    QRegExp phoneRegex("^[0-9\\-\\+\\s\\(\\)]{7,20}$");
    return phoneRegex.exactMatch(phone);
}

// 邮箱格式验证
bool MainWindow::isValidEmail(const QString &email)
{
    QRegExp emailRegex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$");
    return emailRegex.exactMatch(email);
}

2. 数据库设计与实现

2.1 SQLite数据库初始化

使用SQLite作为轻量级数据库,自动创建数据库文件和表结构:

cpp 复制代码
void MainWindow::setupDatabase()
{
    // 创建SQLite数据库
    db = QSqlDatabase::addDatabase("QSQLITE");
    
    // 设置数据库文件路径
    QString dbPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
    QDir().mkpath(dbPath);
    db.setDatabaseName(dbPath + "/contacts.db");
    
    if (!db.open()) {
        QMessageBox::critical(this, "错误", "无法打开数据库: " + db.lastError().text());
        return;
    }
    
    // 创建联系人表
    QSqlQuery query;
    query.exec("CREATE TABLE IF NOT EXISTS contacts ("
               "id INTEGER PRIMARY KEY AUTOINCREMENT,"
               "name TEXT NOT NULL,"
               "phone TEXT NOT NULL,"
               "email TEXT,"
               "address TEXT,"
               "notes TEXT"
               ")");
}
2.2 MVC架构实现

使用QSqlTableModel作为数据模型,QTableView作为视图:

cpp 复制代码
void MainWindow::setupTable()
{
    // 创建数据模型
    contactModel = new QSqlTableModel(this, db);
    contactModel->setTable("contacts");
    contactModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
    
    // 设置表头
    contactModel->setHeaderData(0, Qt::Horizontal, "ID");
    contactModel->setHeaderData(1, Qt::Horizontal, "姓名");
    contactModel->setHeaderData(2, Qt::Horizontal, "电话");
    contactModel->setHeaderData(3, Qt::Horizontal, "邮箱");
    contactModel->setHeaderData(4, Qt::Horizontal, "地址");
    contactModel->setHeaderData(5, Qt::Horizontal, "备注");
    
    // 设置表格视图
    ui->contactTableWidget->setModel(contactModel);
    ui->contactTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->contactTableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
}

3. CRUD操作实现

3.1 添加联系人

通过对话框收集用户输入,验证数据后插入数据库:

cpp 复制代码
void MainWindow::addContact()
{
    if (!contactDialog) {
        contactDialog = new ContactDialog(this);
    }
    
    contactDialog->setContactInfo("", "", "", "", "");
    contactDialog->setWindowTitle("添加联系人");
    
    if (contactDialog->exec() == QDialog::Accepted) {
        QSqlRecord record = contactModel->record();
        record.setValue("name", contactDialog->getName());
        record.setValue("phone", contactDialog->getPhone());
        record.setValue("email", contactDialog->getEmail());
        record.setValue("address", contactDialog->getAddress());
        record.setValue("notes", contactDialog->getNotes());
        
        if (contactModel->insertRecord(-1, record)) {
            contactModel->submitAll();
            showStatusMessage("联系人添加成功");
            contactModel->select();
        } else {
            QMessageBox::warning(this, "错误", "添加联系人失败: " + contactModel->lastError().text());
        }
    }
}
3.2 编辑联系人

获取选中行的数据,在对话框中显示并允许用户修改:

cpp 复制代码
void MainWindow::editContact()
{
    QModelIndex currentIndex = ui->contactTableWidget->currentIndex();
    if (!currentIndex.isValid()) {
        QMessageBox::information(this, "提示", "请先选择一个联系人");
        return;
    }
    
    int row = currentIndex.row();
    QSqlRecord record = contactModel->record(row);
    
    if (!contactDialog) {
        contactDialog = new ContactDialog(this);
    }
    
    contactDialog->setContactInfo(
        record.value("name").toString(),
        record.value("phone").toString(),
        record.value("email").toString(),
        record.value("address").toString(),
        record.value("notes").toString()
    );
    contactDialog->setWindowTitle("编辑联系人");
    
    if (contactDialog->exec() == QDialog::Accepted) {
        record.setValue("name", contactDialog->getName());
        record.setValue("phone", contactDialog->getPhone());
        record.setValue("email", contactDialog->getEmail());
        record.setValue("address", contactDialog->getAddress());
        record.setValue("notes", contactDialog->getNotes());
        
        if (contactModel->setRecord(row, record)) {
            contactModel->submitAll();
            showStatusMessage("联系人更新成功");
            contactModel->select();
        }
    }
}
3.3 删除联系人

安全删除机制,包含确认对话框防止误删:

cpp 复制代码
void MainWindow::deleteContact()
{
    QModelIndex currentIndex = ui->contactTableWidget->currentIndex();
    if (!currentIndex.isValid()) {
        QMessageBox::information(this, "提示", "请先选择一个联系人");
        return;
    }
    
    int row = currentIndex.row();
    QSqlRecord record = contactModel->record(row);
    QString name = record.value("name").toString();
    
    QMessageBox::StandardButton reply = QMessageBox::question(
        this, "确认删除", 
        QString("确定要删除联系人 '%1' 吗?").arg(name),
        QMessageBox::Yes | QMessageBox::No
    );
    
    if (reply == QMessageBox::Yes) {
        if (contactModel->removeRow(row)) {
            contactModel->submitAll();
            showStatusMessage("联系人删除成功");
            contactModel->select();
        }
    }
}

4. 搜索功能实现

4.1 多字段模糊搜索

支持姓名、电话、邮箱、地址、备注的模糊匹配:

cpp 复制代码
void MainWindow::searchContacts()
{
    QString searchText = ui->searchLineEdit->text().trimmed();
    if (searchText.isEmpty()) {
        contactModel->setFilter("");
        showStatusMessage("显示所有联系人");
        contactModel->select();
        clearDetailPanel();
        return;
    }
    
    QString filter = QString("name LIKE '%%1%' OR phone LIKE '%%1%' OR email LIKE '%%1%' OR address LIKE '%%1%' OR notes LIKE '%%1%'")
                    .arg(searchText);
    contactModel->setFilter(filter);
    contactModel->select();
    
    showStatusMessage(QString("找到 %1 个匹配的联系人").arg(contactModel->rowCount()));
    updateDetailPanelForIndex(ui->contactTableWidget->currentIndex());
}
4.2 实时搜索更新

通过信号槽机制实现搜索结果的实时更新:

cpp 复制代码
void MainWindow::setupConnections()
{
    // 搜索功能连接
    connect(ui->searchLineEdit, &QLineEdit::textChanged, this, &MainWindow::searchContacts);
    connect(ui->clearSearchButton, &QPushButton::clicked, this, &MainWindow::clearSearch);
    
    // 表格选择变化
    connect(ui->contactTableWidget->selectionModel(), &QItemSelectionModel::currentRowChanged,
            this, &MainWindow::onCurrentRowChanged);
}

5. 数据导入导出功能

5.1 CSV格式导出

将联系人数据导出为CSV格式文件:

cpp 复制代码
void MainWindow::exportContacts()
{
    QString fileName = QFileDialog::getSaveFileName(this, "导出联系人", 
                                                   "contacts.csv", "CSV文件 (*.csv)");
    if (fileName.isEmpty()) return;
    
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QMessageBox::warning(this, "错误", "无法创建文件");
        return;
    }
    
    QTextStream out(&file);
    out.setCodec("UTF-8");
    
    // 写入表头
    out << "姓名,电话,邮箱,地址,备注\n";
    
    // 写入数据
    for (int row = 0; row < contactModel->rowCount(); ++row) {
        QSqlRecord record = contactModel->record(row);
        out << QString("\"%1\",\"%2\",\"%3\",\"%4\",\"%5\"\n")
               .arg(record.value("name").toString())
               .arg(record.value("phone").toString())
               .arg(record.value("email").toString())
               .arg(record.value("address").toString())
               .arg(record.value("notes").toString());
    }
    
    file.close();
    showStatusMessage("联系人导出成功");
}
5.2 CSV格式导入

从CSV文件导入联系人数据:

cpp 复制代码
void MainWindow::importContacts()
{
    QString fileName = QFileDialog::getOpenFileName(this, "导入联系人", 
                                                   "", "CSV文件 (*.csv)");
    if (fileName.isEmpty()) return;
    
    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        QMessageBox::warning(this, "错误", "无法打开文件");
        return;
    }
    
    QTextStream in(&file);
    in.setCodec("UTF-8");
    
    // 跳过表头
    QString header = in.readLine();
    
    int importedCount = 0;
    while (!in.atEnd()) {
        QString line = in.readLine();
        QStringList fields = parseCSVLine(line);
        
        if (fields.size() >= 2) { // 至少需要姓名和电话
            QSqlRecord record = contactModel->record();
            record.setValue("name", fields[0]);
            record.setValue("phone", fields[1]);
            record.setValue("email", fields.size() > 2 ? fields[2] : "");
            record.setValue("address", fields.size() > 3 ? fields[3] : "");
            record.setValue("notes", fields.size() > 4 ? fields[4] : "");
            
            if (contactModel->insertRecord(-1, record)) {
                importedCount++;
            }
        }
    }
    
    contactModel->submitAll();
    contactModel->select();
    file.close();
    
    showStatusMessage(QString("成功导入 %1 个联系人").arg(importedCount));
}

6. 信号槽机制

6.1 界面交互连接

通过信号槽机制实现界面组件之间的通信:

cpp 复制代码
void MainWindow::setupConnections()
{
    // CRUD操作按钮
    connect(ui->addButton, &QPushButton::clicked, this, &MainWindow::addContact);
    connect(ui->editButton, &QPushButton::clicked, this, &MainWindow::editContact);
    connect(ui->deleteButton, &QPushButton::clicked, this, &MainWindow::deleteContact);
    
    // 搜索功能
    connect(ui->searchLineEdit, &QLineEdit::textChanged, this, &MainWindow::searchContacts);
    connect(ui->clearSearchButton, &QPushButton::clicked, this, &MainWindow::clearSearch);
    
    // 表格交互
    connect(ui->contactTableWidget, &QTableView::doubleClicked, 
            this, &MainWindow::onTableDoubleClicked);
    connect(ui->contactTableWidget->selectionModel(), &QItemSelectionModel::currentRowChanged,
            this, &MainWindow::onCurrentRowChanged);
    
    // 菜单操作
    connect(ui->actionImport, &QAction::triggered, this, &MainWindow::importContacts);
    connect(ui->actionExport, &QAction::triggered, this, &MainWindow::exportContacts);
}
6.2 表格选择变化处理

实时更新详情面板显示选中联系人的信息:

cpp 复制代码
void MainWindow::onCurrentRowChanged(const QModelIndex &current, const QModelIndex &previous)
{
    Q_UNUSED(previous)
    updateDetailPanelForIndex(current);
}

void MainWindow::updateDetailPanelForIndex(const QModelIndex &index)
{
    if (!index.isValid()) {
        clearDetailPanel();
        return;
    }
    
    QSqlRecord record = contactModel->record(index.row());
    ui->detailNameLabel->setText(record.value("name").toString());
    ui->detailPhoneLabel->setText(record.value("phone").toString());
    ui->detailEmailLabel->setText(record.value("email").toString());
    ui->detailAddressLabel->setText(record.value("address").toString());
    ui->detailNotesLabel->setText(record.value("notes").toString());
}

开发环境搭建

1. 安装Qt开发环境

  1. 下载并安装Qt Creator
  2. 配置编译器(推荐使用MinGW或MSVC)
  3. 创建新的Qt Widgets Application项目

2. 项目配置

在.pro文件中配置项目依赖:

qmake 复制代码
QT       += core gui sql

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

SOURCES += \
    main.cpp \
    mainwindow.cpp \
    contactdialog.cpp

HEADERS += \
    mainwindow.h \
    contactdialog.h

FORMS += \
    mainwindow.ui

3. 编译运行

  1. 在Qt Creator中打开项目
  2. 配置构建套件
  3. 点击运行按钮编译并执行程序

项目特色功能

1. 智能数据验证

  • 电话号码格式验证
  • 邮箱地址格式验证
  • 必填字段检查

2. 实时搜索

  • 多字段模糊匹配
  • 实时结果显示
  • 搜索状态提示

3. 数据持久化

  • SQLite数据库存储
  • 自动创建数据库文件
  • 数据安全可靠

4. 用户友好界面

  • 详情面板实时显示
  • 状态栏消息提示
  • 确认对话框防止误操作

5. 数据导入导出

  • CSV格式支持
  • 批量数据处理
  • 编码格式处理

扩展功能建议

1. 高级搜索功能

  • 按分组搜索
  • 按生日搜索
  • 按标签搜索

2. 联系人分组

  • 创建联系人分组
  • 分组管理功能
  • 分组统计信息

3. 生日提醒

  • 生日提醒功能
  • 日历集成
  • 提醒设置

4. 数据备份

  • 自动备份功能
  • 云端同步
  • 数据恢复

5. 界面美化

  • 主题切换
  • 自定义样式
  • 动画效果

性能优化建议

1. 数据库优化

  • 添加索引提高查询性能
  • 使用事务处理批量操作
  • 定期清理无用数据

2. 内存管理

  • 使用智能指针管理动态内存
  • 避免不必要的对象拷贝
  • 及时释放资源

3. 界面优化

  • 虚拟化大列表显示
  • 延迟加载详情信息
  • 异步处理耗时操作

常见问题解决

1. 编译错误

问题: 找不到Qt SQL模块
解决: 在.pro文件中添加 QT += sql

2. 运行时错误

问题: 数据库连接失败
解决: 检查数据库文件路径和权限

3. 数据导入问题

问题: CSV文件编码错误
解决: 确保文件使用UTF-8编码

总结

本项目展示了Qt框架在桌面应用开发中的强大功能,通过合理的架构设计和数据库集成,构建了一个功能完整、界面友好的个人通讯录管理系统。项目涵盖了Qt开发的核心技术点:

  • MVC架构: 使用QSqlTableModel实现数据模型
  • 数据库操作: SQLite数据库的创建和管理
  • 界面设计: 表单布局和对话框设计
  • 信号槽机制: 实现界面组件间的通信
  • 数据验证: 输入数据的格式验证
  • 文件操作: CSV格式的导入导出
  • 错误处理: 完善的异常处理机制

这个项目适合作为Qt数据库应用开发的入门项目,也可以在此基础上扩展更多功能,如联系人分组、生日提醒、数据同步等高级特性。

希望这个教程对您的Qt学习有所帮助!如有问题,欢迎在评论区讨论。


相关资源:

相关推荐
witkey_ak9896几秒前
python 可迭代对象相关知识点
开发语言·python
呼啦啦啦啦啦啦啦啦25 分钟前
synchronized锁,ReentrantLock 锁
开发语言·
听风的码1 小时前
Vue2封装Axios
开发语言·前端·javascript·vue.js
素界UI设计2 小时前
建筑行业变革:用Three.js构建BIM数据可视化孪生平台
开发语言·javascript·信息可视化
戏言zare3 小时前
Qt设置软件使用期限【新版防修改系统时间】
qt
疯狂的代M夫4 小时前
C++对象的内存布局
开发语言·c++
大橘4 小时前
【qml-5】qml与c++交互(类型单例)
qt·qml
mit6.8244 小时前
Linux下C#项目构建
开发语言·c#
群联云防护小杜4 小时前
从一次 DDoS 的“死亡回放”看现代攻击链的进化
开发语言·python·linq