基于QT和mysql的预约管理系统

Posted 杨书落

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于QT和mysql的预约管理系统相关的知识,希望对你有一定的参考价值。

博客说明:这篇博客主要是用来记录QT小白,想学习QT写的一个预约系统。主要记录一些Qt操作数据库的常规操作,和其它一些QT的基础操作,写的代码都是经过验证可以用的,也会有很多不当的操作有错误也属于正常,此篇主要用来记录,尽量把东西写的详细。不解释函数的用法,有需要可以自己去查

目录

QT操作数据库部分

一、QT对mysql数据库的增删改查操作(非可视化数据库)

#define cout qDebug() << "[" << __FILE__ << ":" << __LINE__ << "]"
//不带路径打印日期时间 文件名行号
string fileName = __FILE__;
string::size_type iPos = fileName.find_last_of('/') + 1;
string filename = fileName.substr(iPos, fileName.length() - iPos);
#define cout cout << "[" << __DATE__ << "  " << __TIME__ << '\\t'<< filename << __LINE__  <<  ":" << "]" << "\\t"
这句代码表示用cout代替qDebug(),并打印文件名和行数,这个在调试的时候很有效果

1.1 mysql数据库

这小节主要是说明,Windows10本身是不带MySQL数据库的,所以第一步应该先下载MySql安装配置,可以直接在CSDN上搜一下就有很简单,再下一个Navicat作为数据库管理工具,这个安装配置教程也很多,就不在这里说明了。还有就是本人没有学过数据库,数据库的操作完全是现学现卖,如果有学过的同学欢迎指正错误
注:这章是全用代码实现,下一章是可视化实现

注意点:记住设置的用户名和密码,用户名默认是root

1.2 连接数据库

void Database::ConnectMySql()

//先判断一下这个默认的连接名是否存在,如果不存在才使用addDatabase()方法,如果存在则使用database()方法
	QSqlDatabase db; //申明
	if(QSqlDatabase::contains("qt_sql_default_connection")) 
     db = QSqlDatabase::database("qt_sql_default_connection");
    else 
     db = QSqlDatabase::addDatabase("QMYSQL");  //连接的MYSQL的数据库驱动,如果多个参数要加上一个参数即数据库的名称
   
   query = QSqlQuery(db); //表示连接到db数据库
    db.setHostName("localhost");         //主机名
    db.setPort(3306);                    //端口
    db.setDatabaseName("userpasswd");          //数据库名
    db.setUserName("root");              //用户名
    db.setPassword("123456");            //密码
    db.open();
    //测试连接
    if(!db.open()) 
        cout <<"不能连接"<<"connect to mysql error"<<db.lastError().text();
     else 
         cout <<"连接成功"<<"connect to mysql OK";
    

注意点:这里只要把上述注释的地方换成自己设置的就好了,连接成功会打印
连接成功 connect to mysql OK

1.3 创建表格

1.3.1判断表格是否存在

QStringList strTables = db.tables();
    if (strTables.contains("teacher")) 
        cout << "Exit";
     else 
        isCreat = true;
        cout << "no Exit";
    

1.3.2创建表格

 query.exec("create table admin(id int primary key auto_increment, name varchar(255), passwd varchar(255))");

解释:创建名叫admin的表格,表格里面有name 和 passwd属性都是字符串类型

id int primary key auto_increment //表示设置表格ID可以自动累加
这里的query.exec()返回值是bool类型,可以用来判断成功与否

query.exec(create table 要创建的表名(id int primary key auto_increment, 属性名 类型, 属性名 类型…… ))

1.4 插入数据

  • 单条插入1
query.exec("insert into admin(id, name, passwd) values(1, 'admin', '123')");

解释:在admin表中第一行插入name = admin, passwd = 123,

语法:insert into 表名(1,2,...) values(1,2,....)
  • 单条插入2 — 直接插入value
query.exec("insert into admin values(1, 'admin', '123')");

效果等同于上述1

语法:insert into 表名称 values(1,2,....)
  • 单条插入3 — 插入变量
QString sqlquery = QObject::tr("insert into numcompute values('%1', 'C机房', '%2')")
                .arg(1).arg(NumComputerC);
query.exec(sqlquery);

解释:这里%1%2都是占位符,取.arg()里面的值,这里NumComputerC是变量。

  • 多条插入1 —odbc风格
        query.prepare("insert into admin(name, passwd) values(?, ?)");//id可设可不设会自动生成
        //给字段设置内容 list
        QVariantList nameList;
        nameList << "xiaoming" << "xiaoxiong" << "xianhua";
        QVariantList passwdList;
        passwdList << "123" << "123" << "123";
        //给字段绑定相应的值
        query.addBindValue(nameList);
        query.addBindValue(passwdList);
        //执行预处理命令
        query.execBatch();

解释:数据库的插入语法没有区别,用作为values的占位符
query.prepare()相当于一个插入准备工作,QVariantList 实例化对象类似与qDebug(),keyvalues要一一对应,query.addBindValue()绑定,query.execBatch()query.exec()类似

  • 多条插入2 — oracle风格
 query.prepare("insert into admin(name, passwd) values(:name, :passwd)"); //values里面的值可以自己指定
        //给字段设置内容 list
        QVariantList nameList1;
        nameList1 << "xiaoming" << "xiaoxiong" << "xianhua";
        QVariantList passwdList1;
        passwdList1 << "123" << "123" << "123";
        //给字段绑定相应的值
        query.bindValue(":name", nameList1);
        query.bindValue(":passwd", passwdList1);
        //执行预处理命令
        query.execBatch();

和多条插入一唯一的区别就是占位符不同,这里用实例化对象的时候就不用一一对应了

1.5 表遍历

/*遍历表*/
        QSqlQuery query("select *from numcompute where name = 'A机房'");//遍历A机房, 不指定是所有遍历,加id应该可以确定单元格
        while (query.next())  //按行遍历
          cout << query.value(0).toInt()  //A机房哪一行第1个单元格数据
               << query.value(1).toString()
               << query.value(2).toInt()   ;

        

语法 select *from 表名称 遍历整个表
select *from 表名称 where 列名称 = xxx 遍历xxx那一列的数据
注意点:

  • 这里用query.vakue(即可以是列数(0)开始,也可以是关键字的名字)来遍历到单元格
  • query.next()是一直指向下一条数据,执行完后指在最后,所以如果要遍历表的话,建议用QMap(),有重复keyQMultiMap()用法可以参考c++哈希表用法

1.5.1获取表行列

获取student这个表的行列

        QSqlQuery query("select *from student"); //获取行列
        QSqlRecord rec = query.record();
        cout << "row = " << rec.count() //表一共多少列
             << "line = " << query.size(); //表一共多少行

1.6 更新表数据

QString update = QString("update numcompute set number = '%1' where id = '%2' ").arg(NumComputerC).arg(3);
query.exec(update);

解释: 这里是更新第三行变量NumComputerC的数量
语法1:uodate 表名称 set 列名称 = 新值 WHERE 列名称 = 某值
语法2:update 表名称 set 指定列 = where id = 指定行

1.7删除表格数据

QString sql = QString("delete from apply where applyuser = '%1'").arg(name);
query.exec(sql);

解释:删除单条数据 — 删除apply这个表applyuser这一列等于name的那一行数据

语法:delete from 表名称 where 列名称 = 值

  • 可以在不删除表的情况下删除所有的行。这意味着表的结构、属性和索引都是完整的:

语法:delete* from 表名 *可加可不加

二、QT对MySQL数据库的增删改查操作(可视化数据库)

这一章主要写可视化数据库操作,很方便,可以和第一章配合使用
主要用到Ui设计界面的Table View这个控件,下面的操作都是用按钮设置槽函数在表上直接操作的,如果不会信号与槽可以设置按钮直接右击转到槽,点击时候会调用系统槽函数

2.1 连接数据库

连接这里和1.2节没有区别,如果是直接跳到这里的麻烦跳到1.2看下,连接后加上下面这些代码

 	QSqlTableModel *model = new QSqlTableModel(this);
    //model->setHeaderData(0,Qt::Horizontal,"学号");//需要修改列名可以用这行代码
    model->setEditStrategy(QSqlTableModel::OnManualSubmit);//设置在修改表数据之后,只有手动提交才能生效
    //ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);这个设置可以使得在ui的地方无法修改表中的内容
 	model->setTable("student");//指定访问的数据库中的表
    ui->tableView->setModel(model);//把model放到view中
    model->select();//显示表中的内容

有个注意点:如果有多张表要注意下切换访问的表

:上面设置了手动提交,所以下面的操作都要添加这行代码model->submitAll(),或者直接用个确定按钮来调用这行代码操作才能生效

2.2 插入数据

  QSqlRecord record = model->record() ;//获取一个新行
  int row = model->rowCount();//获取表中的最大数据行
  model->insertRecord(row,record);//在最后插入新行
  model->submitAll();//确认提交

2.3 删除数据

	QItemSelectionModel* smodel = ui->tableView->selectionModel();//获取选中的模型
    QModelIndexList list = smodel->selectedRows();//取出选中模型的索引列表
    for(int i=0;i<list.size();++i)
    
        model->removeRow(list.at(i).row());//删除i所在的索引的行号
    

解释:用鼠标在表格上选取要删除的行,提交操作就可以删除了

		QSqlDatabase::database().transaction();
        QSqlQuery query;
        query.exec(sql);
        //确认删除
        db.commit();
        //回滚,撤销删除
        db.rollback();

解释:上述代码是相当于ctrl+z的操作,可以设置一个撤回的按钮,防止误删

2.4 查询数据

 	QString name = ui->lineEdit->text();//获取要查询的名字
    QString str = QString("name = '%1'").arg(name);//组一个sql语句包
    model->setFilter(str);//设置查询条件
    model->select();//显示查询结果

2.5 取消操作

    model->revertAll();//删除时先撤销所有操作
    model->submitAll();//再提交以上所有操作

解释:取消所有的操作,确定后刚刚的操作都不生效

数据库部分结束:我是基本写完数据库操作后才指导有这个网站的这是个sql的学习网站有兴趣可以看一下,有兴趣的小伙伴可以看里面的语法操作

QT基础操作部分

这部分主要用来记录我写预约系统用到的一些基础操作,每一个估计都不是很全面,仅限我使用的功能,欢迎指正

1 QMessageBox对话框操作

因为用到很多交互,所以对话框必不可少 先实例化对象QMessageBox mess;后面全用mess代替

1.1 基础告知信息

当一个操作结束时你希望有反馈,弹出一个对话框,就用下面的代码

 msgBox.setText("The document has been modified.");
 msgBox.exec();


图片地址

1.2 操作选择对话框

类似于下图,需要你选择

 QCloseEvent *event = new QCloseEvent();
 QMessageBox::StandardButton result=QMessageBox::question(this, "确认", "确定要退出本系统吗?",
                         QMessageBox::Yes|QMessageBox::No,
                         QMessageBox::No);
       if (result==QMessageBox::Yes)
           this->close();
       else
           event->ignore();

解释:参数可以看图。对话框选择默认在No上,点击Yes就会执行this->close

或者你可以将名字改掉,用下面的代码也行

	mess.setWindowTitle("取消预约");
    mess.setText("确定取消预约?");
	mess.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
    mess.setDefaultButton(QMessageBox::Cancel);
    mess.setButtonText(QMessageBox::StandardButton::Yes, QString("确认"));
    mess.setButtonText(QMessageBox::StandardButton::Cancel, QString("取消"));
    int res = mess.exec();

mess.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);这里面还可以加
int res = mess.exec();可以用一个int来获取结果,可以按F1看帮助文档,每个key都有指定的int值,
根据获取的结果用switch case 或者if else等操作来实现功能

2 按钮QPushButton和行编辑lineEdit

2.1 QPushButton

我这里主要用了按钮的两个功能,一个是连接槽函数,实现信号与槽,另一个就是可用不可用,其它的一概没有用到。信号主要是下面几个,信号与槽会在后面章节说。这些信号就是字面意思不难理解

可用不可用主要用了这个函数ui->buttonSure->setEnabled(false); 按钮false表示不可用,true表示可用
有很多控件都可以用这个函数来设置属性

2.2 lineEdit

我主要用到了两个功能,一个是显示数据,一个是读取写入数据

显示数据,首先可以先用setEnabled设置只读,或者有ui界面可以在属性框直接勾选readOnly

这里说一下我当时显示数据遇到的一个问题,就是因为我要获取的数据是登录者的姓名在登录成功后显示在当前界面上,类似下图,所以我要在登录成功界面还没跳转前就要知道。
以下图为例:我用的解决方案是,在这个界面的.h文件中设置一个public变量 如QString m_Name,在登录函数中实例化老师界面的对象Teacher tea,然后直接获取到输入者的姓名tea.m_Name = ui->lineEdit->text();,然后再在这个界面就可以得到登录名。 但是还有一个小问题就是这个m_Name不能放在构造函数中,会被释放,必须放在其它函数中

QString str = ui->lineEdit->text();//获取数据
ui->lineEdit->setText("iiiiii");//设置显示数据

下面是用到的其它操作

ui->lineEdit->setPlaceholderText("输入用户名"); //提示信息
ui->lineEdit->setClearButtonEnabled(true); //设置情况按钮
ui->lineEdit->isClearButtonEnabled(); //开启清空按钮 输入数据后右边会出现一个X
ui->lineEdit->setFocus(); //设置光标焦点  鼠标会在框内
ui->lineEdit->setEchoMode(QLineEdit::Password); //密码隐藏
//ui->lineEdit->setEchoMode(QLineEdit::Normal);  //显示密码

3 回车事件

这个是有默认的函数,可以重写

void keyPressEvent(QKeyEvent *event) //回车事件

    if(event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) 
    

注:Key_Enter是小键盘的确认键,Key_Return是大键盘的回车键

其它的零零碎碎的操作就不说了

4 信号与槽

这与部分我觉得需要自己去看视频或者书,多自己试几次就能够基础掌握

4.1 不带参数的信号槽

注意点:当想实现两个窗口相互发信号的时候,一定要默认一个主窗口,一个子窗口,主窗口包含子窗口的对象,子窗口不包含主窗口对象。子窗口只要负责发出信号,其它的事情都由主窗口实现。

问题注意点:发送信号的对象和接受处理信号的对象,不能在槽函数执行之前死掉,否则会出现信号发出去成功,接受信号的connect返回的也是true但是槽函数就是进不去也不执行。

4.2 带参数的信号槽

写不动了放个老哥的链接带参数的信号槽

总结:

基本都是一些QT的基本操作,对于大佬来说完全是一些废话,对于新手可能也不详尽,仅用来记录学习。望有帮助点个赞。下面放上源码两个没有区别,写的乱七八糟,希望不要吐槽。
链接:百度云
提取码:jukl
csdn链接:大佬有积分也可以下这个CSDN的,需要点积分

以上是关于基于QT和mysql的预约管理系统的主要内容,如果未能解决你的问题,请参考以下文章

基于QT和mysql的预约管理系统

基于QT的空闲教室预约系统[2023-05-29]

基于linux环境下的C++机房预约系统开发

基于SSH的医院挂号预约系统(MySQL版)

java基于微信小程序的新冠疫苗预约系统+ssm+uinapp+Mysql+计算机毕业设计

基于php+mysql的高校体育场地网上预约使用系统