0


用QT链接SQL Server数据库制作交互界面(工资管理系统-数据库)

一、引言

    QT完整源代码贴在文末。入门文章,大佬可直接略过本篇。

    本文仅介绍QT的使用心得以及快速上手的方法,需要读者有一点c++\c的基础,以及会SQL语言和SQL server数据库的使用。

    题目为学校的数据库系统概论的期末专题训练。总用时两天半左右,第一天是QT的安装及了解,第二天继续了解+功能实现,最后半天给成品完善了一下功能和布局。

    在整个过程中产生了许多疑问也走了一些弯路,因此写下此文,旨在帮助像我一样完全没接触过QT或交互界面的朋友快速上手,以制作出最后成品为导向。懂的并不多,如有错误欢迎指出。

    以下是题目要求,不需要的朋友可以跳过:

系统实现:用QT/JAVA SWING/Tkinter等GUI框架开发数据库系统的交互界面。用SQL语言实现数据定义、数据查询和数据更新等操作并实现数据的持久化存储。

**题目三 工资管理系统的设计 **

系统概述:通过对人事管理管理部门中的职称、工资、员工、部门、工资类别等相关内容进行分析,完成具有人员管理、工资管理、部门管理等相关功能的小型数据库管理应用系统,系统需要具备增减工资中应发、应扣类别的灵活性以适应将来需求的变化。

基本要求

1.完成人员、部门、工资类别、职称表的维护

2.根据需要对工资类别进行添加 。

3.完成工资表的生成,并计算相关数据,进行查询。

4.按部门计算平均工资 。

5.按人、年统计平均工资 。

6.完成权限控制功能,如果一个同学独立完成,仅要求简单的用户登录即可。 本题目所需的知识点:E-R关系图、数据库表设计、数据库表维护等。

该题可2个同学完成,各同学题目为:

工资管理系统——基础数据

工资管理系统——工资管理

其中基础数据包括职称、工资、部门、工资类别、员工基本信息的录入、修改、删除、查询、打印。

工资管理包括工资的录入、删除、修改、查询、打印以及相关统计查询等。

二、QT各功能的介绍和解释

    下载安装的方法csdn有很多,不再赘述。链接数据库前需要下载配置ODBC,也有很多文章。

1、QT的创建

    整个项目只用得到创建项目和打开项目这两个按钮。

    点击创建项目,选择第一个QT Widgets Applications,取个名选个路径,选择qmake,然后再base class这一栏选择QWidget(QMainwindow制作起来差不多,我选的是QWidget),然后有一个选择编译工具的,如果有多个就挑着选,都选也行,以创建后不报错为标准。最后一直点下一步直到完成创建。

    此步也有很多教程,所以就简单几句话略过。

2、QT特点介绍:信号与槽

    QT中有一种特殊的概念,叫信号与槽。举个例子,当你在一个窗口上点击一个按钮时,这个按钮相当于向自己所在的界面发出了一个“我被点击了,我要进行相应的动作了”的信号,而槽就是接收这个信号的专门的接收器。可以理解为生物上的激素与受体。如果有读者用过MFC,那这个槽就是MFC中的点击事件。一个按钮(实际上是界面上所以可供交互的组件)相应的执行函数叫槽函数。

3、各文件的意义和交互的设计界面

    点开源文件,双击widget.cpp开始我们的项目,主要的代码都写在这里。main.cpp暂时不用动。

    此处通俗易懂地解释一下,main起的作用跟c++一样,不过在此项目里基本就起一个调出主交互页面(主页面的代码就在widget.cpp里)的作用,起这个作用的就一句话,点开来可以看到:w.show();

    我们继续回到widget.cpp里。第一个类似函数体的大括号,为了简单易懂,我在此不严谨地称之为构造函数(确实有点像),我们的数据库的链接、控制界面的显示、对象和变量的定义新建、信号与槽函数(后面专门介绍)等都在这里进行定义,只有先在此定义了才能在后面使用。在这个文件里还需要写我们实现各种功能的函数,这些函数的定义写在相应的.h文件中,具体实现代码写在.cpp,跟c++一样。(具体形式我会在后面给出)

** 紧接着,我们进入到好玩的、可视化的部分!**

    这也是和交互界面和平常编程的区别和乐趣所在。

    左侧的目录里还有一个“界面文件”,点开,双击widget.ui,我们就会来到如下图所示的ui设计界面。

    左边一列是各种组件,点击拖动到中间的界面上即可自由放置,拉拽四周的点可以放大缩小。右上角这一栏会显示你已经放置上的组件及其名字、属性。双击即可更改相应组件的名字,建议大家取一个自己记得住的名字便于区分。接下来我来简单介绍一下各个组件,以我的界面为例:

    左右两侧的按钮,叫pushButton,在Buttons栏里,作用是点击后完成设定的动作,比如跳转新页面、显示数据等,具体需要自己设定。添加完按钮后系统会自动在.cpp文件中新建一个空的槽函数,我们右键添加的组件,选择“转到槽...”即可跳转到相应的槽函数进行编写。

    中间的空白框是tableview,在Item Views栏,顾名思义是用来显示表格内容的,后续我们会链接数据库然后让数据库中的表在这个组件上显示出来。

    接下来是界面上面:

    ![](https://img-blog.csdnimg.cn/direct/a5fcac76c24b4fbe9a513799b38e0791.png)

    左边的文字点击后没有任何反应,它只是起到标识作用,是display widgets栏中的label组件。

    右边则是一个可供输入的文本框,在input widget是中的line edit。它用来获取用户写在文本框里的内容,然后进行处理或者其他操作。

    以上就是基础的组件及其用途,会使用他们已经可以完成很多窗口的设计了,也足够完成本系统。读者可自行探索更多不同功能的组件。

4、QT的代码应该如何写?写在哪?以什么方式写?

widget.h部分和widget.cpp中构造函数部分的代码

    以下是我项目的widget.cpp中构造函数的源代码:
#include "widget.h"
#include "ui_widget.h"
#include "QMessageBox"
#include "QSqlError"
#include "QSqlQueryModel"
#include <QtDebug>
#include <QStandardItemModel>
#include <QTableView>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    userMode = new QSqlQueryModel(ui->tableView);//绑定

    QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
    db.setHostName("**********");//替换成自己的
    db.setDatabaseName("hhhh");

    // 使用 Windows 身份验证连接数据库
    db.setUserName(""); // 留空以使用 Windows 身份验证
    db.setPassword(""); // 留空以使用 Windows 身份验证

    if(db.open())
    {
        QMessageBox::information(this, "连接提示" ,"连接成功");
    }
    else
    {
        QMessageBox::warning(this, "连接提示" ,"连接失败");
        qDebug() << db.lastError().text(); // 输出错误信息
    }

    // 通过指针创建登录界面类的对象
    m_log = new login;
    // 调用登录窗口的show()函数显示登录界面
    m_log->show();
    m_register = new Lregister;
    // 建立信号槽,当接收到登录界面发来的login()信号后,调用主窗口的show()函数。
    connect(m_log,SIGNAL(log()),this,SLOT(show()));
    // 建立信号槽,当接收到登录界面发来的re()信号后,调用注册窗口的show()函数。
    connect(m_log,SIGNAL(re()),m_register,SLOT(show()));
    // 建立信号槽,当接收到注册界面发来的log2()信号后,调用主窗口的show()函数。
    connect(m_register,SIGNAL(log2()),this,SLOT(show()));
    // 建立信号槽,当接收到注册界面发来的close_window2()信号后,调用登录窗口的close()函数。
    connect(m_register,SIGNAL(close_window2()),m_log,SLOT(close()));

    m0 = new QSqlTableModel;

    m_statistics = new statistics;
}

Widget::~Widget()
{
    delete ui;
}

//显示表employee的内容
void Widget::on_pushButton_displayE_clicked()
{
    m0->setTable("employee");
    ui->tableView->setModel(m0);
    m0->select();
}

//显示表department的内容
void Widget::on_pushButton_displayD_clicked()
{
    m0->setTable("department");
    ui->tableView->setModel(m0);
    m0->select();
}

//显示表profession的内容
void Widget::on_pushButton_displayP_clicked()
{
    m0->setTable("profession");
    ui->tableView->setModel(m0);
    m0->select();
}

//显示表Wcategory的内容
void Widget::on_pushButton_displayW_clicked()
{
    m0->setTable("Wcategory");
    ui->tableView->setModel(m0);
    m0->select();
}

//显示表wage的内容
void Widget::on_pushButton_wage_clicked()
{
    userMode->setQuery("UPDATE wage SET Rwage = Swage - Dwage");

    m0->setTable("wage");
    ui->tableView->setModel(m0);
    m0->select();
}

//查找查询的功能
void Widget::on_pushButton_query_clicked()
{
    QString item = ui->lineEdit_item->text() ;
    QString content = ui->lineEdit_content->text() ;
    QString str  = QString('%1' + " = '%2'").arg(item).arg(content) ;
    userMode->setQuery("SELECT employee.name, employee.id, employee.gender, employee.birthday, employee.department, employee.profession, Wcategory.Wcategory, wage.year, wage.Rwage, wage.Swage, wage.Dwage from employee INNER JOIN wage ON wage.id = employee.id INNER JOIN Wcategory ON Wcategory.Wno = wage.Wno INNER JOIN department ON department.department = employee.department INNER JOIN profession ON profession.profession = employee.profession WHERE employee." + item + " = '" + content + "'");
    ui->tableView->setModel(userMode);
}

//删除所选中行的功能
void Widget::on_pushButton_delete_clicked()
{
    if(rights2 == "普通用户")
    {
        QMessageBox::information(this, "通知", "您无此权限!");
    }
    else if(rights2 == "管理员")
    {
        // 创建确认对话框
        QMessageBox::StandardButton reply;
        reply = QMessageBox::question(this, "确认", "您确定要对选中的行执行删除操作吗?", QMessageBox::Yes | QMessageBox::No);

        // 判断用户的选择
        if (reply == QMessageBox::Yes) {
            QItemSelectionModel *selectionModel = ui->tableView->selectionModel();
            QModelIndexList selectedIndexes = selectionModel->selectedRows();

            QAbstractItemModel *model = ui->tableView->model();

            for (const QModelIndex &selectedIndex : selectedIndexes) {
                model->removeRow(selectedIndex.row());
            }

            ui->tableView->update();
            QMessageBox::information(this, "通知" ,"删除操作成功!");
        } else {
            QMessageBox::information(this, "通知" ,"删除操作已取消!");
        }
    }
    else if (rights2 == "")
    {
        QMessageBox::information(this, "通知" ,"rights2未赋值!");
    }
}

//退出的按钮
void Widget::on_pushButton_exit_clicked()
{
    exit(0);
}

//实现添加的按钮(增加空行)
void Widget::on_pushButton_addrow_clicked()
{
    if(rights2 == "管理员")
    {
        // 获取当前显示的表名
        QString tableName = m0->tableName();

        m0->setTable(tableName);
        ui->tableView->setModel(m0);
        m0->select();
        //加入空行
        m0->insertRow(m0->rowCount());
        m0->submitAll();
    }
    else
    {
        QMessageBox::information(this, "通知", "您无此权限!");
    }
}

//跳转到statistics统计界面的按钮
void Widget::on_pushButton_statistics_clicked()
{
    m_statistics->show();
}

//退出登录的按钮
void Widget::on_pushButton_logout_clicked()
{
    m_log->show();
    this->close();
}
    还有widget.h的完整代码(除了两条虚线之间以及#include部分,其他部分都是创建工程即有的,不需要改动):
#ifndef WIDGET_H
#define WIDGET_H

#include "login.h"
#include "statistics.h"
#include "Lregister.h"

#include <QWidget>
#include <QtSql/QSqlDatabase>
#include <QMessageBox>
#include <QSqlTableModel>
#include <QSqlQuery>
#include <QSqlQueryModel>
#include <QSqlError>

QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

//--------此处添加函数声明!!!!----------
private slots:

    void on_pushButton_displayP_clicked();

    void on_pushButton_displayD_clicked();

    void on_pushButton_displayE_clicked();

    void on_pushButton_displayW_clicked();

    void on_pushButton_query_clicked();

    void on_pushButton_delete_clicked();

    void on_pushButton_add_clicked();

    void on_pushButton_wage_clicked();

    void on_pushButton_kindofwage_clicked();

    void on_pushButton_exit_clicked();

    void on_pushButton_addrow_clicked();

    void on_pushButton_statistics_clicked();

    void on_pushButton_logout_clicked();

//--------此处添加函数声明!!!!----------

//--------此处添加属性定义!!!!----------
private:
    Ui::Widget *ui;
    QSqlQueryModel *userMode;
    QSqlTableModel *m0;
    QSqlTableModel *m1;
    QSqlTableModel *m2;
    QSqlTableModel *m3;
    QSqlTableModel *m4;
    QSqlTableModel *n0;
    QSqlTableModel *model;
    QSqlTableModel *tableView;
    QAbstractItemModel* tn;
    // 登录界面类的对象作为指针
    login * m_log;
    // 统计界面类的对象作为指针
    statistics * m_statistics;

    Lregister * m_register;

//--------此处添加属性定义!!!!----------

};
#endif // WIDGET_H
    以上涉及到的东西有:基本设定、定义与声明(包括信号与槽)、数据库的链接等。我们一个一个来介绍。
基本设定
    .cpp构造函数的代码中,ui->setupUi(this);这句就是对ui的操作,意思是建立ui。这句话一建立项目就有,不用改。

    userMode = new QSqlQueryModel(ui->tableView);//绑定

    上面这句与我们的组件table view的设置有关,不加上这句没法用这个组件。但是需要在.h中添加相应声明(下面会说)。

    可以理解为对使用组件所需要提前写下的基本设定。不需要懂为什么,只需要知道要用table view组件,就必须要这句话。推广开来,很多其他组件也都需要这样的设定。
定义与声明(包括信号与槽)
    与C++一样,属性与成员函数声明写在.h文件,代码具体实现写在.cpp文件(构造函数后)。

    例如,在.cpp里的一个函数,即一个按钮的槽函数on_pushButton_displayE_clicked(),它在.cpp里的代码如下:
//显示表employee的内容
void Widget::on_pushButton_displayE_clicked()
{
    m0->setTable("employee");
    ui->tableView->setModel(m0);
    m0->select();
}
   以上函数中有一个对象m0,它是需要定义才能使用的。通常定义在**构造函数**的最后,也就是上面完整代码的倒数第二句话:m0 = new QSqlTableModel;

    还有我们的信号与槽:
// 建立信号槽,当接收到登录界面发来的login()信号后,调用主窗口的show()函数。
    connect(m_log,SIGNAL(log()),this,SLOT(show()));
    这样形式的就是信号槽,用来接收其他部分发出的信号,然后做出反应。

    格式是:**connect(发出信号的对象名,发出的信号名,接收信号的对象名,接收对象后做出反应的相应函数);**

    上式中,m_log是我制作的登陆界面类的对象名字,发出的信号名叫log(),接收对象的就是现在这个widget窗口,所以是this,然后相应的事件函数名则是show(),即widget自带的一个函数:show(),作用是显示widget窗口。

    整个语句的意思是:当对象m_log(也就是登陆界面)发出一个名叫log()的信号时,会被此窗口(widget)接收到,然后启动widget自带的函数show(),显示此窗口,实现一个登陆后展示主界面的效果。

    当然,m_log也是需要在.h文件声明的,即上面.h完整代码中的 login * m_log; 句。我解释一下,这个login是我制作的登陆界面的文件名,就像widget。这句话的意思是,我定义了一个名字是m_log的、用来指代登录界面login的对象。可以把login看作一个类型,就像是string,char,int。

    而log()函数则是需要在login.cpp和.h中实现的。各个界面文件的实现方法都一样,不再赘述。这里在一个窗口的代码里出现另一个窗口的原因,则是我需要由一个窗口通过满足特定条件来引出另一个窗口。如果窗口数量多且每个窗口都可以引出另一个窗口,那么就可以像串糖葫芦串烧烤一样把他们串起来,甚至还可以变成一个“环”。网上,一些电脑中病毒后会源源不断地跳出新窗口来让电脑崩溃,或许就是这个原理,跟上面不同的是它的条件不需要点击按钮,可能是等待特定时间,比如0.5秒。但是想来应该没有这么简单,我对网安和黑客一窍不通。
数据库的链接
    这部分没什么好说的,写在widget.cpp的构造函数位置。csdn上也有许多贴,照着来就行了,如果出错就多找经验贴。注意windows身份验证和用户名密码这两种方式的区分。

三、项目的整体实现思路

    如图所示:

四、项目各功能思路详细说明

1、主界面

    ![](https://img-blog.csdnimg.cn/direct/4b60ab341c044374a9fc0bb3fb65c2f0.png)

    主界面要实现的功能有以下:在tableview上显示各种表的内容、增、删、改、查、工资情况的自定义统计以及退出界面和退出登录(登出)。

    显示各种表的内容的函数非常简单,以下是显示employee表按钮的槽函数:
//显示表employee的内容
void Widget::on_pushButton_displayE_clicked()
{
    m0->setTable("employee");
    ui->tableView->setModel(m0);
    m0->select();
}
    显示其他表只需把“employee”换成其他的表名就可以了。

    接下来是增、删、改、查。改最简单。我发现tableview本身是自带修改功能的,用法就是显示出表的内容后双击,然后直接修改就行。这个功能不需要写任何代码。如下图所示:

    增加的功能我取了个巧。点击一个按钮实现添加一行空行的功能,然后利用上述修改的功能直接在空行里修改,这样就相当于添加了一行了。如果不想取巧,那么思路是将要添加的内容写在一个个lineEdit中,然后在类似“确定添加”的按钮槽函数中使用SQL语句将获取的lineEdit内容添加进数据库中。就结果而言这二者是一样的。

    接下来是删除。点击表上一行的最左边,可以选中一整行,然后点击删除按钮进行删除。按钮的代码如下(添加了一个弹出对话框进行确认)。

// 创建确认对话框
        QMessageBox::StandardButton reply;
        reply = QMessageBox::question(this, "确认", "您确定要对选中的行执行删除操作吗?", QMessageBox::Yes | QMessageBox::No);

        // 判断用户的选择
        if (reply == QMessageBox::Yes) {
            QItemSelectionModel *selectionModel = ui->tableView->selectionModel();
            QModelIndexList selectedIndexes = selectionModel->selectedRows();

            QAbstractItemModel *model = ui->tableView->model();

            for (const QModelIndex &selectedIndex : selectedIndexes) {
                model->removeRow(selectedIndex.row());
            }

            ui->tableView->update();
            QMessageBox::information(this, "通知" ,"删除操作成功!");
        } else {
            QMessageBox::information(this, "通知" ,"删除操作已取消!");
        }
    最后是查找。原理和添加的常规方法思路一样,不再赘述。源码我会贴在最后。

    接下来是退出。退出界面的按键最简单,槽函数里就一句话:exit(0);

    退出登录即登出,一登出就有登录,这里涉及到登录界面和注册界面的制作。还有工资情况的自定义统计,也涉及到一个新的界面。接下来介绍这两个界面。

2、登陆界面/注册界面

    登录界面我命名为login,注册界面则为lregister。

    主要思路与添加功能相似。注册功能是在数据库中事先创建一个表,用来记录注册的用户名和密码。

    将在lineEdit获取的用户名用SQL语句首先在库中查询是否注册过,若有,弹出提示,若无,就用户名和密码存储进去。

    登录更为简单,只需将已输入的用户名和密码用SQL语句查找是否符合库中的记录。一致则登录。

    这里还涉及到一个权限问题。我只将最初的第一个注册的用户(即管理员)的权限设为管理员,其他后来注册的都默认是普通用户。权限作为一个列名一起放入用户的数据库中。我对权限的设定是:管理员能使用所有功能,但是普通用户不能使用修改、添加和删除功能,只能查看与查找表的内容和工资情况统计。

    对普通用户所能使用的功能的限制如何实现呢?我在普通用户不能使用的三个功能的函数里多加了一个if判断,判断此时用户是否是管理员。为此我设置了一个全局变量int rights = -1,放置在login.cpp的incldue后一行。当我登录时,程序会去寻找此时登录的用户的权限是什么,如果是管理员,则将rights赋值为1,普通用户则为0。同时,在相应限制功能的按钮槽函数中添加if判断,如果rights为0,即普通用户,则弹出弹窗显示无权限(注意,此处跳出的弹窗是小弹窗,或者可以认为是系统环境内置的封装好的窗口,我们不需要自己写,如果想跳出自己写的窗口,则不能使用QMessageBox)。包含权限相关的登录按钮(在login.cpp中)代码如下:
void login::on_pushButton_login_clicked()
{
    // 从输入框获取账号
    QString username = ui->lineEdit_username->text();
    // 从输入框获取密码
    QString password = ui->lineEdit_password->text();

    QSqlQuery query;
    QSqlQuery query2;
    QString sql = "SELECT password FROM user_table WHERE username = '" + username + "'";
    if (!query.exec(sql)) {
        qDebug() << "无此账号!";
        return;
    }

    // 接下来,获取指定位置的数值并保存为QString类型
    if (query.next()) {
        QString value = query.value(0).toString();
        qDebug() << "密码数据找到了: " << value;
        //账号和密码匹配正确
        if (value == password)
        {
            QString sql2 = "SELECT rights FROM user_table WHERE username = '" + username + "'";
            if (!query2.exec(sql2)) {
                qDebug() << "查询语句错误!";
                return;
            }
            if (query2.next())
            {
                QString value2 = query2.value(0).toString();
                qDebug() << "用户权限找到了: " << value2;
                if(value2 == "管理员")
                {
                    QMessageBox::information(this, "通知", "登录成功!您的权限是" + value2 + "权限!");
                    rights = 1;
                    rights2 = value2;
                }
                else if(value2 == "普通用户")
                {
                    QMessageBox::information(this, "通知", "登录成功!您的权限是" + value2 + "权限!");
                    rights = 0;
                    rights2 = value2;
                }
            }
            else
            {
                qDebug() << "寻找权限时出错!";
            }

            emit(log());
            qDebug() << "已发送log信号";
            emit(close_window());
        }
        else // 账号或密码错误
            QMessageBox::information(this, "错误" ,"账号或密码错误!");
    } else {
        qDebug() << "寻找数据时出错!";
    }
}
    如何限制权限的代码以删除为例:
//删除所选中行的功能
void Widget::on_pushButton_delete_clicked()
{
    if(rights2 == "普通用户")
    {
        QMessageBox::information(this, "通知", "您无此权限!");
    }
    else if(rights2 == "管理员")
    {
        // 创建确认对话框
        QMessageBox::StandardButton reply;
        reply = QMessageBox::question(this, "确认", "您确定要对选中的行执行删除操作吗?", QMessageBox::Yes | QMessageBox::No);

        // 判断用户的选择
        if (reply == QMessageBox::Yes) {
            QItemSelectionModel *selectionModel = ui->tableView->selectionModel();
            QModelIndexList selectedIndexes = selectionModel->selectedRows();

            QAbstractItemModel *model = ui->tableView->model();

            for (const QModelIndex &selectedIndex : selectedIndexes) {
                model->removeRow(selectedIndex.row());
            }

            ui->tableView->update();
            QMessageBox::information(this, "通知" ,"删除操作成功!");
        } else {
            QMessageBox::information(this, "通知" ,"删除操作已取消!");
        }
    }
    else if (rights2 == "")
    {
        QMessageBox::information(this, "通知" ,"rights2未赋值!");
    }
}
    接下来还有2点很重要。1、如何在主界面前先显示登录界面;2、如何登录成功后跳出主界面(也就是widget界面),即如何使一个窗口拥有弹出另一个窗口的能力。

    我们先将第二点。想要使一个窗口拥有弹出另一个窗口的能力很简单,即让被呼出的窗口在发起呼出动作的窗口里包含就行了。然后需要在发起呼出的界面的.h文件中声明一下,具体参见上文**定义与声明**的部分。

    然后我们只需要一个发起动作的信号,来让新窗口跳出。具体使用的就是信号与槽,参见上文的定义与声明部分。请记得connect开头的那个语句要写在被调出的界面的.cpp里。

    在发起呼出的界面.cpp中,我们需要一个语句来发出信号:
            emit(re());
   re()是一个函数名,可以自己定义。这个函数就是connect后面跟着的四个参数的第二个。

    第一点,我需要先解释一下。我们点开man.cpp文件,我们可以看到有一句:
            w.show();
    这句话的意思是,整个项目一启动,第一个跳出来的界面就是主界面widget,而不是我们想要的登陆界面。相应的解决办法是

3、统计界面

    即工资情况的自定义统计界面,我命名为statistics。

    这有四个按钮,分别是四个模块,每个模块对应一个按钮,每个按钮点击后会弹出一个新的窗口。我把4个新窗口展示在下面。

    年度平均工资界面,我命名为qyear:

    个人工资界面,我命名为qname:

    部门平均工资界面,我命名为qdepartment:

    职位平均工资界面,我命名为qprofession:

    这几个没什么好说的,跟查找功能一样,获取lineEdit内容然后在槽函数中进行查找然后处理运算,如何运算根据具体要求来。

五、补充

    有一些针对用户体验的小细节我就没讲,读者要是有相应需求可以自行研究,比如进行重要操作时的确认弹窗、撤销功能、管理员可以对赋权限给普通用户的权限管理功能,还有记住密码功能。

    还有一些很小的地方,但是对于用户体验来说不算小。比如在输入完成用户名和密码后,多数人习惯直接按下Enter回车键来代替鼠标对登录按钮的点击。

    这些都是完全可以实现的,我因为时间不够,没有完全优化这些功能,但是可以给其中的一些功能提供简单的思路。

    确认弹窗可以使用内置的QMessageBox。

    记住密码功能,可以创建一个txt文件,在登录时储存这次登录的用户名和密码,下次登录时可供读取。每次往里储存时记得比较一下是否和已经记载的数据一直,不一致则清空txt再进行储存。

    权限管理功能本质上就是对数据库指定内容的修改。

    Enter键代替鼠标点击的实现csdn有帖子,不敢班门弄斧。

六、完整源码

    main.cpp:
#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{

    QApplication a(argc, argv);
    Widget w;
    //w.show();
    return a.exec();
}
   widget.h:
#ifndef WIDGET_H
#define WIDGET_H

#include "login.h"
#include "statistics.h"
#include "Lregister.h"

#include <QWidget>
#include <QtSql/QSqlDatabase>
#include <QMessageBox>
#include <QSqlTableModel>
#include <QSqlQuery>
#include <QSqlQueryModel>
#include <QSqlError>

QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:

    void on_pushButton_displayP_clicked();

    void on_pushButton_displayD_clicked();

    void on_pushButton_displayE_clicked();

    void on_pushButton_displayW_clicked();

    void on_pushButton_query_clicked();

    void on_pushButton_delete_clicked();

    void on_pushButton_add_clicked();

    void on_pushButton_wage_clicked();

    void on_pushButton_kindofwage_clicked();

    void on_pushButton_exit_clicked();

    void on_pushButton_addrow_clicked();

    void on_pushButton_statistics_clicked();

    void on_pushButton_logout_clicked();

private:
    Ui::Widget *ui;
    QSqlQueryModel *userMode;
    QSqlTableModel *m0;
    QSqlTableModel *m1;
    QSqlTableModel *m2;
    QSqlTableModel *m3;
    QSqlTableModel *m4;
    QSqlTableModel *n0;
    QSqlTableModel *model;
    QSqlTableModel *tableView;
    QAbstractItemModel* tn;
    // 登录界面类的对象作为指针
    login * m_log;
    // 统计界面类的对象作为指针
    statistics * m_statistics;

    Lregister * m_register;

};
#endif // WIDGET_H
    widget.cpp:
#include "widget.h"
#include "ui_widget.h"
#include "QMessageBox"
#include "QSqlError"
#include "QSqlQueryModel"
#include <QtDebug>
#include <QStandardItemModel>
#include <QTableView>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    userMode = new QSqlQueryModel(ui->tableView);//绑定

    QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
    db.setHostName("LAPTOP-PFEJR2BB");
    db.setDatabaseName("hhhh");

    // 使用 Windows 身份验证连接数据库
    db.setUserName(""); // 留空以使用 Windows 身份验证
    db.setPassword(""); // 留空以使用 Windows 身份验证

    if(db.open())
    {
        QMessageBox::information(this, "连接提示" ,"连接成功");
    }
    else
    {
        QMessageBox::warning(this, "连接提示" ,"连接失败");
        qDebug() << db.lastError().text(); // 输出错误信息
    }

    // 通过指针创建登录界面类的对象
    m_log = new login;
    // 调用登录窗口的show()函数显示登录界面
    m_log->show();
    m_register = new Lregister;
    // 建立信号槽,当接收到登录界面发来的login()信号后,调用主窗口的show()函数。
    connect(m_log,SIGNAL(log()),this,SLOT(show()));
    // 建立信号槽,当接收到登录界面发来的re()信号后,调用注册窗口的show()函数。
    connect(m_log,SIGNAL(re()),m_register,SLOT(show()));
    // 建立信号槽,当接收到注册界面发来的log2()信号后,调用主窗口的show()函数。
    connect(m_register,SIGNAL(log2()),this,SLOT(show()));
    // 建立信号槽,当接收到注册界面发来的close_window2()信号后,调用登录窗口的close()函数。
    connect(m_register,SIGNAL(close_window2()),m_log,SLOT(close()));

    m0 = new QSqlTableModel;

    m_statistics = new statistics;
}

Widget::~Widget()
{
    delete ui;
}

//显示表employee的内容
void Widget::on_pushButton_displayE_clicked()
{
    m0->setTable("employee");
    ui->tableView->setModel(m0);
    m0->select();
}

//显示表department的内容
void Widget::on_pushButton_displayD_clicked()
{
    m0->setTable("department");
    ui->tableView->setModel(m0);
    m0->select();
}

//显示表profession的内容
void Widget::on_pushButton_displayP_clicked()
{
    m0->setTable("profession");
    ui->tableView->setModel(m0);
    m0->select();
}

//显示表Wcategory的内容
void Widget::on_pushButton_displayW_clicked()
{
    m0->setTable("Wcategory");
    ui->tableView->setModel(m0);
    m0->select();
}

//显示表wage的内容
void Widget::on_pushButton_wage_clicked()
{
    userMode->setQuery("UPDATE wage SET Rwage = Swage - Dwage");

    m0->setTable("wage");
    ui->tableView->setModel(m0);
    m0->select();
}

//查找查询的功能
void Widget::on_pushButton_query_clicked()
{
    QString item = ui->lineEdit_item->text() ;
    QString content = ui->lineEdit_content->text() ;
    QString str  = QString('%1' + " = '%2'").arg(item).arg(content) ;
    userMode->setQuery("SELECT employee.name, employee.id, employee.gender, employee.birthday, employee.department, employee.profession, Wcategory.Wcategory, wage.year, wage.Rwage, wage.Swage, wage.Dwage from employee INNER JOIN wage ON wage.id = employee.id INNER JOIN Wcategory ON Wcategory.Wno = wage.Wno INNER JOIN department ON department.department = employee.department INNER JOIN profession ON profession.profession = employee.profession WHERE employee." + item + " = '" + content + "'");
    ui->tableView->setModel(userMode);
}

//删除所选中行的功能
void Widget::on_pushButton_delete_clicked()
{
    if(rights2 == "普通用户")
    {
        QMessageBox::information(this, "通知", "您无此权限!");
    }
    else if(rights2 == "管理员")
    {
        // 创建确认对话框
        QMessageBox::StandardButton reply;
        reply = QMessageBox::question(this, "确认", "您确定要对选中的行执行删除操作吗?", QMessageBox::Yes | QMessageBox::No);

        // 判断用户的选择
        if (reply == QMessageBox::Yes) {
            QItemSelectionModel *selectionModel = ui->tableView->selectionModel();
            QModelIndexList selectedIndexes = selectionModel->selectedRows();

            QAbstractItemModel *model = ui->tableView->model();

            for (const QModelIndex &selectedIndex : selectedIndexes) {
                model->removeRow(selectedIndex.row());
            }

            ui->tableView->update();
            QMessageBox::information(this, "通知" ,"删除操作成功!");
        } else {
            QMessageBox::information(this, "通知" ,"删除操作已取消!");
        }
    }
    else if (rights2 == "")
    {
        QMessageBox::information(this, "通知" ,"rights2未赋值!");
    }
}

//退出的按钮
void Widget::on_pushButton_exit_clicked()
{
    exit(0);
}

//实现添加的按钮(增加空行)
void Widget::on_pushButton_addrow_clicked()
{
    if(rights2 == "管理员")
    {
        // 获取当前显示的表名
        QString tableName = m0->tableName();

        m0->setTable(tableName);
        ui->tableView->setModel(m0);
        m0->select();
        //加入空行
        m0->insertRow(m0->rowCount());
        m0->submitAll();
    }
    else
    {
        QMessageBox::information(this, "通知", "您无此权限!");
    }
}

//跳转到statistics统计界面的按钮
void Widget::on_pushButton_statistics_clicked()
{
    m_statistics->show();
}

//退出登录的按钮
void Widget::on_pushButton_logout_clicked()
{
    m_log->show();
    this->close();
}
    login.h:
#ifndef LOGIN_H
#define LOGIN_H

#include <QWidget>
#include <QSqlQuery>
#include <QMessageBox>

extern int rights;
extern QString rights2;

namespace Ui {
class login;
}

class login : public QWidget
{
    Q_OBJECT

public:
    explicit login(QWidget *parent = nullptr);
    ~login();

signals:
    void log(); //登录主界面信号
    void close_window(); //关闭登录界面信号
    void re();

private slots:
    void on_pushButton_login_clicked();

    void on_pushButton_exit_clicked();

    void on_pushButton_register_clicked();

    void on_pushButton_Lregister_clicked();

private:
    Ui::login *ui;

};

#endif // LOGIN_H
    login,cpp:
#include "login.h"
#include "ui_login.h"
#include <QMessageBox>

int rights = -1;
QString rights2 = "";

login::login(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::login)
{
    ui->setupUi(this);

    // 发出信号后关闭登录窗口的信号槽连接
    connect(this,SIGNAL(close_window()),this,SLOT(close()));

    ui->lineEdit_password->setEchoMode(QLineEdit::Password);//输入时显示圆点
}

login::~login()
{
    delete ui;
}

void login::on_pushButton_login_clicked()
{
    // 从输入框获取账号
    QString username = ui->lineEdit_username->text();
    // 从输入框获取密码
    QString password = ui->lineEdit_password->text();

    QSqlQuery query;
    QSqlQuery query2;
    QString sql = "SELECT password FROM user_table WHERE username = '" + username + "'";
    if (!query.exec(sql)) {
        qDebug() << "无此账号!";
        return;
    }

    // 接下来,获取指定位置的数值并保存为QString类型
    if (query.next()) {
        QString value = query.value(0).toString();
        qDebug() << "密码数据找到了: " << value;
        //账号和密码匹配正确
        if (value == password)
        {
            QString sql2 = "SELECT rights FROM user_table WHERE username = '" + username + "'";
            if (!query2.exec(sql2)) {
                qDebug() << "查询语句错误!";
                return;
            }
            if (query2.next())
            {
                QString value2 = query2.value(0).toString();
                qDebug() << "用户权限找到了: " << value2;
                if(value2 == "管理员")
                {
                    QMessageBox::information(this, "通知", "登录成功!您的权限是" + value2 + "权限!");
                    rights = 1;
                    rights2 = value2;
                }
                else if(value2 == "普通用户")
                {
                    QMessageBox::information(this, "通知", "登录成功!您的权限是" + value2 + "权限!");
                    rights = 0;
                    rights2 = value2;
                }
            }
            else
            {
                qDebug() << "寻找权限时出错!";
            }

            emit(log());
            qDebug() << "已发送log信号";
            emit(close_window());
        }
        else // 账号或密码错误
            QMessageBox::information(this, "错误" ,"账号或密码错误!");
    } else {
        qDebug() << "寻找数据时出错!";
    }
}

void login::on_pushButton_exit_clicked()
{
    exit(0);
}

void login::on_pushButton_Lregister_clicked()
{
    emit(re());
    qDebug() << "已发送re信号";
}
    lregister.h:
#ifndef LREGISTER_H
#define LREGISTER_H

#include <QWidget>
#include <QString>
#include <QSqlQuery>
#include <QMessageBox>

namespace Ui {
class Lregister;
}

class Lregister : public QWidget
{
    Q_OBJECT

public:
    explicit Lregister(QWidget *parent = nullptr);
    ~Lregister();

signals:
    void log2(); //登录主界面信号
    void close_window2(); //关闭注册界面和登录的信号
    void close_window3(); //只关闭注册界面的信号

private slots:
    void on_pushButton_register_clicked();

    void on_pushButton_cancel_clicked();

private:
    Ui::Lregister *ui;
};

#endif // LREGISTER_H
    lregister.cpp:
#include "lregister.h"
#include "ui_lregister.h"

Lregister::Lregister(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Lregister)
{
    ui->setupUi(this);

    // 发出信号后关闭注册窗口的信号槽连接
    connect(this,SIGNAL(close_window2()),this,SLOT(close()));
    // 发出信号后关闭注册窗口的信号槽连接
    connect(this,SIGNAL(close_window3()),this,SLOT(close()));

    ui->lineEdit_password->setEchoMode(QLineEdit::Password);//输入时显示圆点
    ui->lineEdit_Apassword->setEchoMode(QLineEdit::Password);//输入时显示圆点
}

Lregister::~Lregister()
{
    delete ui;
}

void Lregister::on_pushButton_register_clicked()
{
    // 从输入框获取账号
    QString username = ui->lineEdit_username->text();
    // 从输入框获取密码
    QString password = ui->lineEdit_password->text();
    // 从输入框获取确认密码
    QString Apassword = ui->lineEdit_Apassword->text();

    QSqlQuery query;
    QSqlQuery query2;
    QString sql = "SELECT password FROM user_table WHERE username = '" + username + "'";
    QString sql2 = "INSERT INTO user_table (username, password, rights) VALUES ('" + username + "', '" + password +"', '普通用户');";
    if (query.exec(sql))
    {
        if (!query.next())
        {
            qDebug() << "此用户名不重复,可以注册! ";
            if(password == Apassword)
            {
                if (query2.exec(sql2))
                {
                    QMessageBox::information(this, "通知", "注册成功!权限为普通用户权限!");
                    // 创建确认对话框
                    QMessageBox::StandardButton reply;
                    reply = QMessageBox::question(this, "选择", "您想现在登录此账号吗?", QMessageBox::Yes | QMessageBox::No);
                    // 判断用户的选择
                    if (reply == QMessageBox::Yes)
                    {
                        emit(log2());
                        qDebug() << "已发送log2信号";
                        emit(close_window2());
                    }
                    else
                    {
                        emit(close_window2());
                    }
                }
                else
                {
                    QMessageBox::information(this, "通知", "注册失败!");
                }
            }
            else
            {
                QMessageBox::information(this, "通知", "确认密码与密码不一致!请重新输入!");
            }

        }
        else
        {
            QMessageBox::information(this, "通知", "sql2语句错误!");
        }
    }
    else
    {
        QMessageBox::information(this, "通知", "sql语句错误!");
    }
}

void Lregister::on_pushButton_cancel_clicked()
{
    emit(close_window3());
}
    staistics.h:
#ifndef STATISTICS_H
#define STATISTICS_H

#include <QWidget>
#include "qyear.h"
#include "qname.h"
#include "qdepartment.h"
#include "qprofession.h"

namespace Ui {
class statistics;
}

class statistics : public QWidget
{
    Q_OBJECT

public:
    explicit statistics(QWidget *parent = nullptr);
    ~statistics();

private slots:
    void on_pushButton_Qyear_clicked();

    void on_pushButton_Qname_clicked();

    void on_pushButton_Qdepartment_clicked();

    void on_pushButton_Qprofession_clicked();

private:
    Ui::statistics *ui;

    // 按年份统计界面类的对象作为指针
    Qyear * m_Qyear;
    // 按人统计界面类的对象作为指针
    Qname * m_Qname;
    // 按部门统计界面类的对象作为指针
    Qdepartment * m_Qdepartment;
    // 按职位统计界面类的对象作为指针
    Qprofession * m_Qprofession;

};

#endif // STATISTICS_H

statistics.cpp:

#include "statistics.h"
#include "ui_statistics.h"

statistics::statistics(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::statistics)
{
    ui->setupUi(this);

    m_Qyear = new Qyear;
    m_Qname = new Qname;
    m_Qdepartment = new Qdepartment;
    m_Qprofession = new Qprofession;
}

statistics::~statistics()
{
    delete ui;
}

void statistics::on_pushButton_Qyear_clicked()
{
    m_Qyear->show();
}

void statistics::on_pushButton_Qname_clicked()
{
    m_Qname->show();
}

void statistics::on_pushButton_Qdepartment_clicked()
{
    m_Qdepartment->show();
}

void statistics::on_pushButton_Qprofession_clicked()
{
    m_Qprofession->show();
}
    qyear.h:
#ifndef QYEAR_H
#define QYEAR_H

#include <QWidget>

namespace Ui {
class Qyear;
}

class Qyear : public QWidget
{
    Q_OBJECT

public:
    explicit Qyear(QWidget *parent = nullptr);
    ~Qyear();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Qyear *ui;
};

#endif // QYEAR_H
    qyear.cpp:
#include "qyear.h"
#include "ui_qyear.h"
#include <QMessageBox>
#include <QSqlQuery>
#include <QSqlQueryModel>

Qyear::Qyear(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Qyear)
{
    ui->setupUi(this);

}

Qyear::~Qyear()
{
    delete ui;
}

void Qyear::on_pushButton_clicked()
{
    QString year = ui->lineEdit_year->text();
    QSqlQuery query;
    if (!year.isEmpty()) {
        query.prepare("SELECT 4*AVG(Rwage) AS avg_wage "
                      "FROM wage "
                      "JOIN Wcategory ON wage.Wno = Wcategory.Wno "
                      "JOIN employee ON wage.id = employee.id "
                      "WHERE wage.year = '" + year + "' ");
    }
    else
    {
        QMessageBox::warning(this, "错误" ,"请输入年份!");
    }

    if (!query.exec()) {
        QMessageBox::critical(this, "错误", "查询失败!");
        return;
    }

    // 获取结果并显示到lineEdit_result中
    if (query.next()) {
        QString averageWage = query.value("avg_wage").toString();
        ui->lineEdit_result->setText(averageWage);
        QMessageBox::information(this, year + "年的人均总工资",
                                 QString( year + "年的人均总工资为:%1")
                                     .arg(averageWage));
    }
    else
    {
        QMessageBox::information(this, "错误", "找不到结果!错误!");
    }

}
    qname.h:
#ifndef QNAME_H
#define QNAME_H

#include <QWidget>

namespace Ui {
class Qname;
}

class Qname : public QWidget
{
    Q_OBJECT

public:
    explicit Qname(QWidget *parent = nullptr);
    ~Qname();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Qname *ui;
};

#endif // QNAME_H
    qname.cpp:
#include "qname.h"
#include "ui_qname.h"
#include <QMessageBox>
#include <QSqlQuery>
#include <QSqlQueryModel>

Qname::Qname(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Qname)
{
    ui->setupUi(this);
}

Qname::~Qname()
{
    delete ui;
}

void Qname::on_pushButton_clicked()
{
    QString name = ui->lineEdit_name->text();
    QSqlQuery query;
    if (!name.isEmpty()) {
        query.prepare("SELECT sum(Rwage) AS avg_wage "
                      "FROM wage "
                      "JOIN Wcategory ON wage.Wno = Wcategory.Wno "
                      "JOIN employee ON wage.id = employee.id "
                      "WHERE employee.name = '" + name + "' ");
    }
    else
    {
        QMessageBox::warning(this, "错误" ,"请输入员工姓名!");
    }

    if (!query.exec()) {
        QMessageBox::critical(this, "错误", "查询失败!");
        return;
    }

    // 获取结果并显示到lineEdit_result中
    if (query.next()) {
        QString averageWage = query.value("avg_wage").toString();
        ui->lineEdit_result->setText(averageWage);
        QMessageBox::information(this, "员工" + name + "的年均总工资",
                                 QString("员工" + name + "的年均总工资为: %1")
                                     .arg(averageWage));
    }
    else
    {
        QMessageBox::information(this, "错误", "找不到结果!错误!");
    }
}
    qdepartment.h:
#ifndef QDEPARTMENT_H
#define QDEPARTMENT_H

#include <QWidget>

namespace Ui {
class Qdepartment;
}

class Qdepartment : public QWidget
{
    Q_OBJECT

public:
    explicit Qdepartment(QWidget *parent = nullptr);
    ~Qdepartment();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Qdepartment *ui;
};

#endif // QDEPARTMENT_H
    qdepartment.cpp:
#include "qdepartment.h"
#include "ui_qdepartment.h"
#include <QMessageBox>
#include <QSqlQuery>
#include <QSqlQueryModel>

Qdepartment::Qdepartment(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Qdepartment)
{
    ui->setupUi(this);
}

Qdepartment::~Qdepartment()
{
    delete ui;
}

void Qdepartment::on_pushButton_clicked()
{
    QString department = ui->lineEdit_department->text();
    QSqlQuery query;
    if (!department.isEmpty()) {
        query.prepare("SELECT 4*AVG(Rwage) AS avg_wage "
                      "FROM wage "
                      "JOIN Wcategory ON wage.Wno = Wcategory.Wno "
                      "JOIN employee ON wage.id = employee.id "
                      "WHERE employee.department = '" + department + "' ");
    }
    else
    {
        QMessageBox::warning(this, "错误" ,"请输入部门!");
    }

    if (!query.exec()) {
        QMessageBox::critical(this, "错误", "查询失败!");
        return;
    }

    // 获取结果并显示到lineEdit_result中
    if (query.next()) {
        QString averageWage = query.value("avg_wage").toString();
        ui->lineEdit_result->setText(averageWage);
        QMessageBox::information(this, department + " 部门的人均年均总工资",
                                 QString( department + " 部门的人均年均总工资为: %1")
                                     .arg(averageWage));
    }
    else
    {
        QMessageBox::information(this, "错误", "找不到结果!错误!");
    }
}
    qprofession.h:
#ifndef QPROFESSION_H
#define QPROFESSION_H

#include <QWidget>

namespace Ui {
class Qprofession;
}

class Qprofession : public QWidget
{
    Q_OBJECT

public:
    explicit Qprofession(QWidget *parent = nullptr);
    ~Qprofession();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Qprofession *ui;
};

#endif // QPROFESSION_H
    qprofession.cpp:
#include "qprofession.h"
#include "ui_qprofession.h"
#include <QMessageBox>
#include <QSqlQuery>
#include <QSqlQueryModel>

Qprofession::Qprofession(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Qprofession)
{
    ui->setupUi(this);
}

Qprofession::~Qprofession()
{
    delete ui;
}

void Qprofession::on_pushButton_clicked()
{
    QString profession = ui->lineEdit_profession->text();
    QSqlQuery query;
    if (!profession.isEmpty()) {
        query.prepare("SELECT 4*AVG(Rwage) AS avg_wage "
                      "FROM wage "
                      "JOIN Wcategory ON wage.Wno = Wcategory.Wno "
                      "JOIN employee ON wage.id = employee.id "
                      "WHERE employee.profession = '" + profession + "' ");
    }
    else
    {
        QMessageBox::warning(this, "错误" ,"请输入职位!");
    }

    if (!query.exec()) {
        QMessageBox::critical(this, "错误", "查询失败!");
        return;
    }

    // 获取结果并显示到lineEdit_result中
    if (query.next()) {
        QString averageWage = query.value("avg_wage").toString();
        ui->lineEdit_result->setText(averageWage);
        QMessageBox::information(this, profession + " 职位的人均年均总工资",
                                 QString( profession + " 职位的人均年均总工资为: %1")
                                     .arg(averageWage));
    }
    else
    {
        QMessageBox::information(this, "错误", "找不到结果!错误!");
    }
}
    各个窗口我都是直接拖组件然后调大小,没有使用代码进行修改,因此只放图片。

    登录界面login:

    注册界面lregister:

    主界面widget:

    工资统计界面statistics:

    年度平均工资界面qyear:

    个人工资qname:

    部门平均工资qdepartment:

    职位平均工资qprofession:

七、结语

    再次声明,本篇仅是为了初学QT的朋友快速上手而作,大佬可直接忽略此文。写下此文也是想记录一下自己制作的心路历程,毕竟是自己第一次接触类似ui的东西,也对这种窗口的制作产生了兴趣。

    谨以此文,纪念自己大学前两年半的计算机所学。希望未来我能在自己感兴趣的领域越走越远,越走越深,也希望未来的自己回望一生时,不会因虚度年华而悔恨。愿常有书籍电影相伴,常有知己相知,常有爱人相爱。
标签: 数据库 qt 交互

本文转载自: https://blog.csdn.net/qq_65449388/article/details/136140409
版权归原作者 飞檐流丹 所有, 如有侵权,请联系我们删除。

“用QT链接SQL Server数据库制作交互界面(工资管理系统-数据库)”的评论:

还没有评论