cdma 电信基站管理项目-2

01-1. "主窗口"添加滚动条

效果图:

mainwindow.cpp

#include "mainwindow.h"

#include "logindlg.h"

#include <QMessageBox>

#include <QIcon> //窗口图标用到此类

MainWindow::MainWindow(QWidget *parent)

    : QMainWindow(parent)

{

    //设置窗口标题

    this->setWindowTitle("CDMA无线基站管理系统");

    //设置窗口图标

    //QIcon icon("./images/main.png");

    //setWindowIcon(icon);

    setWindowIcon(QIcon("./images/main.png"));//设置窗口图标

    //设置多文档界面中央控件

    //QMdiArea控件只能在QMainWindow当中使用,是用来实现多文档界面的必备控件

    //多文档界面控件,也是一种窗口的中央控件,在这个中央控件中可以添加多个控件

    mdiArea = new QMdiArea;

    setCentralWidget(mdiArea);

    //中央控件背景设置

    mdiArea->setBackground(Qt::NoBrush);

    //mdiArea->setStyleSheet("background-color: blue");//设置背景颜色

    //mdiArea->setStyleSheet("border-image: url(./images/1.jpg)");//单张图片拉伸铺满

    mdiArea->setStyleSheet("background-image: url(./images/1.jpg)");//图片重复铺满

    //添加滚动条, 当子窗口的边框,超过父窗口的显示范围时,父窗口自动添加滚动条

    mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);//横向滚动条

    mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);//纵向滚动条

    createAction();//创建菜单项

    createMenus(); //创建菜单

}

01-2. '执行脚本'的菜单项, 关联'数据表格'窗口

效果图:

mainwindow.h

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include <QMainWindow>

#include <QMenu>

#include <QMenuBar>

#include <QAction>

#include <QCloseEvent>

#include <QMdiArea> //多文档界面中央控件支持

class MainWindow : public QMainWindow

{

    Q_OBJECT

public:

    MainWindow(QWidget *parent = nullptr);

    ~MainWindow();

    //重载

    void closeEvent(QCloseEvent *event);

private:

    void createMenus(); //创建菜单的函数

    void createAction();//创建菜单项的函数

    void showsub();//"执行脚本"的菜单项, 添加显示子窗口的函数

    void showview();//显示'数据表'窗口

    //多文档界面中央控件支持

    QMdiArea *mdiArea;

   

    ///菜单

    QMenu *adminMenu; //"管理"菜单

    QMenu *dataMenu;  //"数据"菜单

    QMenu *windowMenu;//"窗口"菜单

    QMenu *helpMenu;  //"帮助"菜单

    ///"管理"菜单的菜单项

    QAction *loginAction; //"登录"菜单项

    QAction *logoutAction;//"注销"菜单项

    QAction *exitAction;  //"退出"菜单项

    ///"数据"菜单的菜单项

    QAction *scriptAction;//"执行脚本"菜单项

    ///"窗口"菜单的菜单项

    QAction *cascadeAction;//"层叠窗口"菜单项

    QAction *tileAction;//"并列窗口"菜单项

    ///"帮助"菜单的菜单项

    QAction *helpAction;//"帮助"菜单项

    QAction *aboutAction;//"关于"菜单项

//槽函数

private slots:

    void on_login(); //"登录"菜单项的响应槽函数

    void on_logout();//"注销"菜单项的响应槽函数

    void on_exit();  //"退出"菜单项的响应槽函数

    void on_script();//"执行脚本"菜单项的槽函数

    void cascadeSubWindows();//"层叠窗口"菜单项的响应槽函数

    void titleSubWindows();//"并列窗口"菜单项的响应槽函数

    void on_help();//"帮助"菜单项的响应槽函数

    void on_about();//"关于"菜单项的响应槽函数

};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"

#include "logindlg.h"

#include <QMessageBox>

#include <QMdiSubWindow>

#include <QIcon> //窗口图标用到此类

#include <QStandardItemModel> //在内存中建立数据表

#include <QTableView>//显示数据表

/**

 * "执行脚本"菜单项的响应槽函数

 */

void MainWindow::on_script()

{

    //QMessageBox::information(this, "", "hello world");

    // showsub();//调用"显示子窗口"的函数

    showview();//显示数据表格窗口

}

/**

 * @ 显示数据表

 */

void MainWindow::showview()

{

    ///创建存储数据的model, 在内存中建立53列的数据表

    QStandardItemModel *model = new QStandardItemModel(5, 3);

    //设置数据表的列名

    //参数1:表示从第几列开始设置 //参数2:Horizontal表示水平(横向)设置

    //参数3:表示要设置的列名

    model->setHeaderData(0, Qt::Horizontal, "姓名");

    model->setHeaderData(1, Qt::Horizontal, "性别");

    model->setHeaderData(2, Qt::Horizontal, "年龄");

    //设置数据表的每一个单元格的内容

    model->setData(model->index(0, 0, QModelIndex()), "张三");

    model->setData(model->index(0, 1, QModelIndex()), "");

    model->setData(model->index(0, 2, QModelIndex()), "20");

    model->setData(model->index(1, 0, QModelIndex()), "李四");

    model->setData(model->index(1, 1, QModelIndex()), "");

    model->setData(model->index(1, 2, QModelIndex()), "30");

    ///创建视图

    QTableView *view1 = new QTableView;

    //设置视图, 当关闭主窗口时, 自动释放"view1"子窗口的资源,也会自动删除model的资源

    view1->setAttribute(Qt::WA_DeleteOnClose);

    //"视图"添加到多文档中央控件, 也主是将"视图"作为子窗口, 内嵌到主窗口之内

    mdiArea->addSubWindow(view1);

    view1->setWindowTitle("bbb");//设置子窗口标题

    view1->setStyleSheet("background-image: url(3.jpg)");//图片重复铺满

    //将存储数据的model保存到view1视图

    view1->setModel(model);

    view1->show();//显示视图

    //activeSubWindow()方法永远返回当前活动的子窗口, 再用 resize()改变当前活动主窗口的大小

    mdiArea->activeSubWindow()->resize(width()-100, height()-100);

}

01-3. 创建执行SQL的对话框

效果图:

添加类文件:

1. 右键"项目"  ---添加新文件

    ---C++  ---C++ Class

   

    类名: ScriptDlg

    基类: 选择"自定义"

        手动输入"QDialog"

scriptdlg.h

#ifndef SCRIPTDLG_H

#define SCRIPTDLG_H

#include <QDialog>

#include <QLabel>

#include <QTextEdit>

#include <QPushButton>

#include <QGridLayout> //网格布局

#include <QHBoxLayout> //水平布局

class ScriptDlg : public QDialog

{

    //启动Qt元对象系统的一些特性(比如支持信号和槽等)

    Q_OBJECT

public:

    // 构造函数, explicit 修饰构造函数, 用于禁止隐式转换

    // 参数定义了对话框对象的父窗口部件,默认NULL意味着自定义的对话框没有父窗口部件

    explicit ScriptDlg(QWidget *parent = nullptr);

private:

    QLabel *label0;

    QTextEdit *textEditSQL;//多行文本框

    QPushButton *okBtn;//执行按钮

    QPushButton *cancelBtn;//取消按钮

//信号

signals:

//槽函数

public slots:

};

#endif // SCRIPTDLG_H

scriptdlg.cpp

#include "scriptdlg.h"

ScriptDlg::ScriptDlg(QWidget *parent) : QDialog(parent)

{

    label0 = new QLabel;

    label0->setText("请输入SQL");

    //创建多选文本框

    textEditSQL = new QTextEdit;//多选文本框

    //创建按钮

    okBtn = new QPushButton;

    okBtn->setText("执行");

    cancelBtn = new QPushButton;

    cancelBtn->setText("取消");

    //创建网格布局

    QGridLayout *layout1 = new QGridLayout(this);

    layout1->addWidget(label0, 0, 0);

    layout1->addWidget(textEditSQL, 0, 1);//'多行文本框'添加到布局

    //创建水平布局, 因为要放入网格布局,所以不需要this

    QHBoxLayout *layout2 = new QHBoxLayout;

    //"按钮"控件添加到水平布局

    layout2->addWidget(okBtn);

    layout2->addWidget(cancelBtn);

    //将水平布局添加网格布局

    layout1->addLayout(layout2, 1, 1);

}

mainwindow.cpp

#include "mainwindow.h"

#include "logindlg.h"

#include "scriptdlg.h"

#include <QMessageBox>

#include <QMdiSubWindow>

#include <QIcon> //窗口图标用到此类

#include <QStandardItemModel> //在内存中建立数据表

#include <QTableView>//显示数据表

/**

 * "执行脚本"菜单项的响应槽函数

 */

void MainWindow::on_script()

{

    //QMessageBox::information(this, "", "hello world");

    // showsub();//调用"显示子窗口"的函数

    // showview();//显示数据表格窗口

    ScriptDlg dlg; //创建scriptDlg类的实例

    dlg.exec(); //显示模式对话框

}

02. 远程登录 mysql

效果图:

cdma.pro 项目配制文件

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

# windows下引用第三方库的方法

LIBS += -LD:/Program1/mysql-5.7.31/lib -llibmysql

# linux下引用第三方库的方法

#LIBS += -lmysqlclient

添加类文件:

1. 右键"项目"  ---添加新文件

    ---C++  ---C++ Class

   

    类名: MyMysql

mymysql.h

#ifndef MYMYSQL_H

#define MYMYSQL_H

//包含SOCKET数据类型, 必须放在包含mysql.h之前

#include <windows.h>

#include "D:/Program1/mysql-5.7.31/include/mysql.h"

class MyMysql

{

public:

    MyMysql();

    //声明连接函数(远程IP地址, 用户名, 密码, 数据库名)

    int sql_connect(const char *Hostname, const char *User, const char *Password, const char *DBName);

private:

    MYSQL *connection;

    MYSQL mysql;

};

#endif // MYMYSQL_H

mymysql.cpp

#include "mymysql.h"

#include <QMessageBox>

MyMysql::MyMysql()

{

    //mysql 初始化

    mysql_init(&mysql);

    connection = nullptr;

}

/**

 * @ 连接到 mysql

 * @param Hostname  mysql服务器主机地址

 * @param User      mysql数据库的用户名

 * @param Password  mysql数据库的密码

 * @param DBName    为要连接的数据库名称

 * @return

 */

int MyMysql::sql_connect(const char *Hostname, const char *User, const char *Password, const char *DBName)

{

    connection = mysql_real_connect(&mysql, Hostname, User, Password, DBName, 0, nullptr, 0);

    if(connection == nullptr)

    {

        //如果连接失败, 弹出一个消息提示框

        QMessageBox::information(nullptr, "", mysql_error(&mysql));

        return -1;

    }else

    {

        return 0;

    }

}

mainwindow.h

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include "mymysql.h"

#include <QMainWindow>

#include <QMenu>

#include <QMenuBar>

#include <QAction>

#include <QCloseEvent>

#include <QMdiArea> //多文档界面中央控件支持

class MainWindow : public QMainWindow

{

    Q_OBJECT

public:

    MainWindow(QWidget *parent = nullptr);

    ~MainWindow();

    //重载

    void closeEvent(QCloseEvent *event);

private:

    MyMysql db;//连接mysql的实例

    void createMenus(); //创建菜单的函数

    void createAction();//创建菜单项的函数

    void showsub();//"执行脚本"的菜单项, 添加显示子窗口的函数

    void showview();//显示'数据表'窗口

mainwindow.cpp

#include "mainwindow.h"

#include "logindlg.h"

#include "scriptdlg.h"

#include <QMessageBox>

#include <QMdiSubWindow>

#include <QIcon> //窗口图标用到此类

#include <QStandardItemModel> //在内存中建立数据表

#include <QTableView>//显示数据表

/**

 * "登录"菜单项的响应槽函数

 */

void MainWindow::on_login()

{

//    QMessageBox::information(this, "", "hello world");

    LoginDlg dlg;//实例化登录对话框

    //dlg.show();//产生一个非模式对话框

    dlg.exec();//调用exec产生一个模式对话框(不能操作其它的对话框)

    //如何在这里获取用户名,密码,IP等用户输入的信息呢?

    //QMessageBox::information(this, "用户名", dlg.userid);

    //如果标志位为true, 表示用户点击了登录按钮

    if(dlg.islogin)

    {

        MyMysql db;

        //连接数据库

        int res = db.sql_connect(

                       dlg.hostip.toStdString().data(), //数据库服务器IP地址

                       dlg.userid.toStdString().data(), //用户名

                       dlg.passwd.toStdString().data(), //密码

                       dlg.dbname.toStdString().data()); //数据库名称

        if(res == -1)

        {

            QMessageBox::information(this, "", "登录失败!");

        }else

        {

            QMessageBox::information(this, "", "登录成功!");

        }

    }

}

测试:

1. 项目引用本地的"libmysql.dll"库为64位版本, 编译项目时要使用64位编译器

    // LIBS += -LD:/Program1/mysql-5.7.31/lib -llibmysql

    "D:\Program1\mysql-5.7.31\lib\libmysql.dll"

2. 运行项目 --管理 --登录, 填写相关参数

3. 点击"登录"按钮, 提示登录成功表示程序正常

04. 返回登录mysql的错误信息

效果图:

mymysql.h

#ifndef MYMYSQL_H

#define MYMYSQL_H

//windows 下使用mysql.h的方式

//<windows.h>必须放在包含mysql.h之前

#include <windows.h>

#include "D:/Program1/mysql-5.7.31/include/mysql.h"

//linux 下使用mysql.h的方式

//#include </usr/local/mysql-5.7.38/include/mysql.h>

class MyMysql

{

public:

    MyMysql();

    //声明连接函数(远程IP地址, 用户名, 密码, 数据库名)

    int sql_connect(const char *Hostname, const char *User, const char *Password, const char *DBName);

    const char *geterror(); //返回错误信息

private:

    MYSQL *connection;

    MYSQL mysql;

    char buf[1024];//用来保存错误信息

};

#endif // MYMYSQL_H

mymysql.cpp

#include "mymysql.h"

#include <QMessageBox>

MyMysql::MyMysql()

{

    //mysql 初始化

    mysql_init(&mysql);

    connection = nullptr;

    memset(buf, 0, sizeof(buf));//清空buf

}

/**

 * @ 连接到 mysql

 * @param Hostname  mysql服务器主机地址

 * @param User      mysql数据库的用户名

 * @param Password  mysql数据库的密码

 * @param DBName    为要连接的数据库名称

 * @return

 */

int MyMysql::sql_connect(const char *Hostname, const char *User, const char *Password, const char *DBName)

{

    connection = mysql_real_connect(&mysql, Hostname, User, Password, DBName, 0, nullptr, 0);

    if(connection == nullptr)

    {

        memset(buf, 0, sizeof(buf)); //清空 buf

        strcpy(buf,  mysql_error(&mysql));//将错误提示信息保存到buf

        return -1;

    }else

    {

        return 0;

    }

}

/**

 * @ 返回保存在buf中的错误信息

 */

const char* MyMysql::geterror()

{

    return buf;

}

mainwindow.cpp

/**

 * "登录"菜单项的响应槽函数

 */

void MainWindow::on_login()

{

//    QMessageBox::information(this, "", "hello world");

    LoginDlg dlg;//实例化登录对话框

    //dlg.show();//产生一个非模式对话框

    dlg.exec();//调用exec产生一个模式对话框(不能操作其它的对话框)

    //如何在这里获取用户名,密码,IP等用户输入的信息呢?

    //QMessageBox::information(this, "用户名", dlg.userid);

    //如果标志位为true, 表示用户点击了登录按钮

    if(dlg.islogin)

    {

        //连接数据库

        int res = db.sql_connect(

                       dlg.hostip.toStdString().data(), //数据库服务器IP地址

                       dlg.userid.toStdString().data(), //用户名

                       dlg.passwd.toStdString().data(), //密码

                       dlg.dbname.toStdString().data()); //数据库名称

        //连接失败

        if(res == -1)

        {

            // QMessageBox::information(this, "失败", "登录失败!");

            //弹出错误提示信息:

            QMessageBox::information(this, "失败", db.geterror());

        }else

        {

            QMessageBox::information(this, "成功", "登录成功!");

        }

    }

}

05-1. 在注销的槽函数中断开mysql连接

mymysql.h

#ifndef MYMYSQL_H

#define MYMYSQL_H

//windows 下使用mysql.h的方式

//<windows.h>必须放在包含mysql.h之前

#include <windows.h>

#include "D:/Program1/mysql-5.7.31/include/mysql.h"

//linux 下使用mysql.h的方式

//#include </usr/local/mysql-5.7.38/include/mysql.h>

class MyMysql

{

public:

    MyMysql();

    //声明连接函数(远程IP地址, 用户名, 密码, 数据库名)

    int sql_connect(const char *Hostname, const char *User, const char *Password, const char *DBName);

    const char *geterror(); //返回错误信息

    void sql_disconnect();//断开mysql连接

private:

    MYSQL *connection;

    MYSQL mysql;

    char buf[1024];//用来保存错误信息

};

#endif // MYMYSQL_H

mymysql.cpp

#include "mymysql.h"

#include <QMessageBox>

MyMysql::MyMysql()

{

    //mysql 初始化

    mysql_init(&mysql);

    connection = nullptr;

    memset(buf, 0, sizeof(buf));//清空buf

}

/**

 * @ 连接到 mysql

 * @param Hostname  mysql服务器主机地址

 * @param User      mysql数据库的用户名

 * @param Password  mysql数据库的密码

 * @param DBName    为要连接的数据库名称

 * @return

 */

int MyMysql::sql_connect(const char *Hostname, const char *User, const char *Password, const char *DBName)

{

    connection = mysql_real_connect(&mysql, Hostname, User, Password, DBName, 0, nullptr, 0);

    if(connection == nullptr)

    {

        memset(buf, 0, sizeof(buf)); //清空 buf

        strcpy(buf,  mysql_error(&mysql));//将错误提示信息保存到buf

        return -1;

    }else

    {

        return 0;

    }

}

/**

 * @ 返回保存在buf中的错误信息

 */

const char* MyMysql::geterror()

{

    return buf;

}

/**

 * @ 断开mysql连接

 */

void MyMysql::sql_disconnect()

{

    if(connection)

    {

        mysql_close(connection);

        connection = NULL;

    }

}

mainwindow.cpp

/**

 * "注销"菜单项的响应槽函数

 */

void MainWindow::on_logout()

{

    QMessageBox::StandardButton button;

    button = QMessageBox::question(this, "提示", "是否注销",

                                   QMessageBox::Yes | QMessageBox::No);

    if(button == QMessageBox::Yes)

    {

        db.sql_disconnect();//断开mysql连接

        scriptAction->setEnabled(false);//设置"执行脚本"菜单项为"不可用状态"

    }

}

05-2. 执行"增删改"SQL语句

mymysql.h

#ifndef MYMYSQL_H

#define MYMYSQL_H

//windows 下使用mysql.h的方式

//<windows.h>必须放在包含mysql.h之前

#include <windows.h>

#include "D:/Program1/mysql-5.7.31/include/mysql.h"

//linux 下使用mysql.h的方式

//#include </usr/local/mysql-5.7.38/include/mysql.h>

#include <QStandardItemModel>

class MyMysql

{

public:

    MyMysql();

    //声明连接函数(远程IP地址, 用户名, 密码, 数据库名)

    int sql_connect(const char *Hostname, const char *User, const char *Password, const char *DBName);

    const char *geterror(); //返回错误信息

    void sql_disconnect();//断开mysql连接

   

    //执行"增删改"SQL语句

    int sql_exec(const char *SQL);

    //执行查询的SQL语句

    int sql_open(const char *SQL, QStandardItemModel **p);

private:

    MYSQL *connection;

    MYSQL mysql;

    char buf[1024];//用来保存错误信息

};

#endif // MYMYSQL_H

mymysql.cpp

#include "mymysql.h"

#include <QMessageBox>

MyMysql::MyMysql()

{

    //mysql 初始化

    mysql_init(&mysql);

    connection = nullptr;

    memset(buf, 0, sizeof(buf));//清空buf

}

/**

 * @ 连接到 mysql

 * @param Hostname  mysql服务器主机地址

 * @param User      mysql数据库的用户名

 * @param Password  mysql数据库的密码

 * @param DBName    为要连接的数据库名称

 * @return

 */

int MyMysql::sql_connect(const char *Hostname, const char *User, const char *Password, const char *DBName)

{

    connection = mysql_real_connect(&mysql, Hostname, User, Password, DBName, 0, nullptr, 0);

    if(connection == nullptr)

    {

        memset(buf, 0, sizeof(buf)); //清空 buf

        strcpy(buf,  mysql_error(&mysql));//将错误提示信息保存到buf

        return -1;

    }else

    {

        //连接mysql成功, 设置数据库的字符集

        mysql_query(connection, "set names utf8");

        return 0;

    }

}

/**

 * @ 返回保存在buf中的错误信息

 */

const char* MyMysql::geterror()

{

    return buf;

}

/**

 * @ 断开mysql连接

 */

void MyMysql::sql_disconnect()

{

    if(connection)

    {

        mysql_close(connection);

        connection = nullptr;

    }

}

/**

 * @ 执行查询的SQL语句

 */

int MyMysql::sql_exec(const char *SQL)

{

    if (mysql_query(connection, SQL) != 0)

    {

        memset(buf, 0, sizeof(buf));

        strcpy(buf, mysql_error(&mysql));

        return -1;

    }

    return 0;

}

mainwindow.cpp

/**

 * "执行脚本"菜单项的响应槽函数

 */

void MainWindow::on_script()

{

    //QMessageBox::information(this, "", "hello world");

    // showsub();//调用"显示子窗口"的函数

    // showview();//显示数据表格窗口

    ScriptDlg dlg; //创建scriptDlg类的实例

    // dlg.exec(); //显示模式对话框

    // db.sql_exec() 执行SQL"增删改"语句

    if(db.sql_exec("delete from table1 where name='张三'") == -1)

    {

       QMessageBox::information(this, "sql_exec()失败!", db.geterror());

    }else

    {

        QMessageBox::information(this, "执行成功", "执行成功!");

}

}

05-3. 执行"脚本对话框", 用户输入的SQL语句

效果图:

update table1 set age=88 where name='李四';

scriptdlg.h

#ifndef SCRIPTDLG_H

#define SCRIPTDLG_H

#include <QDialog>

#include <QLabel>

#include <QTextEdit>

#include <QPushButton>

#include <QGridLayout> //网格布局

#include <QHBoxLayout> //水平布局

class ScriptDlg : public QDialog

{

    //启动Qt元对象系统的一些特性(比如支持信号和槽等)

    Q_OBJECT

public:

    // 构造函数, explicit 修饰构造函数, 用于禁止隐式转换

    // 参数定义了对话框对象的父窗口部件,默认NULL意味着自定义的对话框没有父窗口部件

    explicit ScriptDlg(QWidget *parent = nullptr);

    QString SQL; //保存用户输入的SQL语句

    bool islogin; //用户是否登录mysql的标志

private:

    QLabel *label0;

    QTextEdit *textEditSQL; //多行文本框

    QPushButton *okBtn; //"执行"按钮

    QPushButton *cancelBtn; //"取消"按钮

//信号

signals:

//槽函数

public slots:

    void okBtnOnclick(); //"执行"按钮的槽函数

    void cancelBtnOnclick(); //"取消"按钮的槽函数

};

#endif // SCRIPTDLG_H

scriptdlg.cpp

#include "scriptdlg.h"

ScriptDlg::ScriptDlg(QWidget *parent) : QDialog(parent)

{

    label0 = new QLabel;

    label0->setText("请输入SQL");

    //创建多选文本框

    textEditSQL = new QTextEdit;//多选文本框

    //创建按钮

    okBtn = new QPushButton;

    okBtn->setText("执行");

    cancelBtn = new QPushButton;

    cancelBtn->setText("取消");

    //创建网格布局

    QGridLayout *layout1 = new QGridLayout(this);

    layout1->addWidget(label0, 0, 0);

    layout1->addWidget(textEditSQL, 0, 1);//'多行文本框'添加到布局

    //创建水平布局, 因为要放入网格布局,所以不需要this

    QHBoxLayout *layout2 = new QHBoxLayout;

    //"按钮"控件添加到水平布局

    layout2->addWidget(okBtn);

    layout2->addWidget(cancelBtn);

    //将水平布局添加网格布局

layout1->addLayout(layout2, 1, 1);

    //为按钮关联槽函数

    connect(okBtn, SIGNAL(clicked()), this, SLOT(okBtnOnclick()));

    connect(cancelBtn, SIGNAL(clicked()), this, SLOT(cancelBtnOnclick()));

}

/**

 * @ "执行"按钮的槽函数

 */

void ScriptDlg::okBtnOnclick()

{

    //保存用户输入的SQL语句

    SQL = textEditSQL->toPlainText();

    islogin = true;//设置用户登录状态

    close();//关闭脚本窗口

}

/**

 * @ "取消"按钮的槽函数

 */

void ScriptDlg::cancelBtnOnclick()

{

    close();//关闭脚本窗口

}

mainwindow.cpp

/**

 * "执行脚本"菜单项的响应槽函数

 */

void MainWindow::on_script()

{

    //QMessageBox::information(this, "", "hello world");

    // showsub();//"显示子窗口"的函数

    // showview();//显示数据表格窗口

    ScriptDlg dlg; //创建scriptDlg类的实例

     dlg.exec(); //显示模式对话框

     // db.sql_exec() 执行SQL"增删改"语句

     if(db.sql_exec(dlg.SQL.toStdString().data()) == -1)

     {

        QMessageBox::information(this, "sql_exec()失败!", db.geterror());

     }else

     {

         QMessageBox::information(this, "执行成功", "执行成功!");

     }

}

06-1. 程序优化

mainwindow.cpp

1. "未登录"状态下, "执行脚本"菜单项设置为"不可用"状态

/**

 * 创建菜单项

 */

void MainWindow::createAction()

{

    ///"数据"菜单的菜单项

    //创建"执行脚本"菜单项

    scriptAction = new QAction(tr("执行脚本"), this);

    scriptAction->setShortcut(tr("Ctrl+t"));//快捷键

    scriptAction->setEnabled(false);//"执行脚本"菜单项设置为"不可用"状态

    //"执行脚本"菜单项关联槽函数

    connect(scriptAction, SIGNAL(triggered()), this, SLOT(on_script()));

}

2. 登录成功, "执行脚本"菜单项设置为"可用状态"

/**

 * "登录"菜单项的响应槽函数

 */

void MainWindow::on_login()

{

        //连接失败

        if(res == -1)

        {

            // QMessageBox::information(this, "失败", "登录失败!");

            //弹出错误提示信息:

            QMessageBox::information(this, "失败", db.geterror());

        }else

        {

            QMessageBox::information(this, "成功", "登录成功!");

            scriptAction->setEnabled(true); //登录成功, "执行脚本"菜单项设置为可用状态

        }

}

3. 用户注销后, "执行脚本"菜单项设置为"不可用状态"

/**

 * "注销"菜单项的响应槽函数

 */

void MainWindow::on_logout()

{

    QMessageBox::StandardButton button;

    button = QMessageBox::question(this, "提示", "是否注销",

                                   QMessageBox::Yes | QMessageBox::No);

    if(button == QMessageBox::Yes)

    {

        db.sql_disconnect();//断开mysql连接

        scriptAction->setEnabled(false);//设置"执行脚本"菜单项为"不可用状态"

    }

}

"执行脚本"对话框中, 增加是否点击了"执行按钮"的状态标志

scriptdlg.h

class ScriptDlg : public QDialog

{

    //启动Qt元对象系统的一些特性(比如支持信号和槽等)

    Q_OBJECT

public:

    // 构造函数, explicit 修饰构造函数, 用于禁止隐式转换

    // 参数定义了对话框对象的父窗口部件,默认NULL意味着自定义的对话框没有父窗口部件

    explicit ScriptDlg(QWidget *parent = nullptr);

    QString SQL; //保存用户输入的SQL语句

    bool islogin; //用户是否登录mysql的状态

scriptdlg.cpp

1. 在构造函数中, 初始化"状态"false

ScriptDlg::ScriptDlg(QWidget *parent) : QDialog(parent)

{

    islogin = false;//初始化状态为false

}

2. 用户点击"执行"按钮后,  设置"状态"true

void ScriptDlg::okBtnOnclick()

{

    //保存用户输入的SQL语句

    SQL = textEditSQL->toPlainText();

    islogin = true;//表示用户点击了执行按钮

    close();//关闭脚本窗口

}

mainwindow.cpp

/**

 * "执行脚本"菜单项的响应槽函数

 */

void MainWindow::on_script()

{

    //QMessageBox::information(this, "", "hello world");

    // showsub();//调用"显示子窗口"的函数

    // showview();//显示数据表格窗口

    ScriptDlg dlg; //创建scriptDlg类的实例

    dlg.exec(); //显示模式对话框

    //如果用户点击了"执行"按钮, 才执行SQL语句

    if(dlg.islogin)

    {

        // db.sql_exec() 执行SQL"增删改"语句

        if(db.sql_exec(dlg.SQL.toStdString().data()) == -1)

        {

            QMessageBox::information(this, "sql_exec()失败!", db.geterror());

        }else

        {

            QMessageBox::information(this, "执行成功", "执行成功!");

        }

    }

}

06-2. 执行"查询"SQL语句

mainwindow.

class MainWindow : public QMainWindow

{

    Q_OBJECT

public:

    MainWindow(QWidget *parent = nullptr);

    ~MainWindow();

    //重载

    void closeEvent(QCloseEvent *event);

private:

    MyMysql db;//连接mysql的实例

    void createMenus(); //创建菜单的函数

    void createAction();//创建菜单项的函数

    void showsub();//"执行脚本"的菜单项, 添加显示子窗口的函数

    void showview();//显示'数据表'窗口

    void script_msg(const char *SQL);//执行SQL的函数

mainwindow.cpp

/**

 * "执行脚本"菜单项的响应槽函数

 */

void MainWindow::on_script()

{

    //QMessageBox::information(this, "", "hello world");

    // showsub();//调用"显示子窗口"的函数

    // showview();//显示数据表格窗口

    ScriptDlg dlg; //创建scriptDlg类的实例

    dlg.exec(); //显示模式对话框

    if(dlg.islogin) //如果用户点击了"执行"按钮

    {

        //调用执行SQL的函数

        script_msg(dlg.SQL.toStdString().data());

    }

}

/**

 * @ 调用执行SQL的函数

 */

void MainWindow::script_msg(const char *SQL)

{

    int res = 0;

    //判断SQL语句是否以"select"开头

    if ((strncmp(SQL, "SELECT", 6) == 0) || (strncmp(SQL, "select", 6) == 0))

    {

        QStandardItemModel *modul = nullptr;

        //如果是SELECT,那么执行sql_open这个函数

        res = db.sql_open(SQL, &modul);

        QTableView *view1 = new QTableView;

        //viewclose的时候自动会delete,这个时候如果viewmodul的话,这个modul会被view自动释放。

        view1->setAttribute(Qt::WA_DeleteOnClose);

        //"view1"子窗口添加到多文档中央控件, 实现多文档界面, 其实就是子窗口被"内嵌"在主窗口内的效果

        mdiArea->addSubWindow(view1);

        view1->setStyleSheet("border-image: url(./images/3.jpg);");//设置widget背景图片

        //modul保存到view1,如果没有modul,那么view不会显示任何数据.

        view1->setModel(modul);

        view1->show(); //显示子窗口

        //"多文档中央控件"设置窗口尺寸

        mdiArea->activeSubWindow()->resize(width() - 100, height() - 100);

    }else

    {

        //如果用户执行的不是select语句, 那么执行sql_exec函数

        res = db.sql_exec(SQL);

    }

    //判断执行结果

    if (res == -1)

    {

        QMessageBox::information(this, "执行失败", db.geterror());

    }else

    {

        QMessageBox::information(this, "提示", "执行成功");

    }

}

mymysql.h

#ifndef MYMYSQL_H

#define MYMYSQL_H

//windows 下使用mysql.h的方式

//<windows.h>必须放在包含mysql.h之前

#include <windows.h>

#include "D:/Program1/mysql-5.7.31/include/mysql.h"

//linux 下使用mysql.h的方式

//#include </usr/local/mysql-5.7.38/include/mysql.h>

#include <QStandardItemModel>

class MyMysql

{

public:

    MyMysql();

    //声明连接函数(远程IP地址, 用户名, 密码, 数据库名)

    int sql_connect(const char *Hostname, const char *User, const char *Password, const char *DBName);

    const char *geterror(); //返回错误信息

    void sql_disconnect();//断开mysql连接

   

    //执行"增删改"SQL语句

    int sql_exec(const char *SQL);

    //执行查询的SQL语句

    int sql_open(const char *SQL, QStandardItemModel **p);

private:

    MYSQL *connection;

    MYSQL mysql;

    char buf[1024];//用来保存错误信息

};

#endif // MYMYSQL_H

mymysql.cpp

#include "mymysql.h"

#include <QMessageBox>

MyMysql::MyMysql()

{

    //mysql 初始化

    mysql_init(&mysql);

    connection = nullptr;

    memset(buf, 0, sizeof(buf));//清空buf

}

/**

 * @ 连接到 mysql

 * @param Hostname  mysql服务器主机地址

 * @param User      mysql数据库的用户名

 * @param Password  mysql数据库的密码

 * @param DBName    为要连接的数据库名称

 * @return

 */

int MyMysql::sql_connect(const char *Hostname, const char *User, const char *Password, const char *DBName)

{

    connection = mysql_real_connect(&mysql, Hostname, User, Password, DBName, 0, nullptr, 0);

    if(connection == nullptr)

    {

        memset(buf, 0, sizeof(buf)); //清空 buf

        strcpy(buf,  mysql_error(&mysql));//将错误提示信息保存到buf

        return -1;

    }else

    {

        //连接mysql成功, 设置数据库的字符集

        mysql_query(connection, "set names utf8");

        return 0;

    }

}

/**

 * @ 返回保存在buf中的错误信息

 */

const char* MyMysql::geterror()

{

    return buf;

}

/**

 * @ 断开mysql连接

 */

void MyMysql::sql_disconnect()

{

    if(connection)

    {

        mysql_close(connection);

        connection = nullptr;

    }

}

/**

 * @ 执行"增删改"SQL语句

 */

int MyMysql::sql_exec(const char *SQL)

{

    if (mysql_query(connection, SQL) != 0)

    {

        memset(buf, 0, sizeof(buf));

        strcpy(buf, mysql_error(&mysql));

        return -1;

    }

    return 0;

}

/**

 * @ 执行查询的SQL语句

 */

int MyMysql::sql_open(const char *SQL, QStandardItemModel **p)

{

    // 如果执行失败

    if (mysql_query(connection, SQL) != 0)

    {

        memset(buf, 0, sizeof(buf));

        strcpy(buf, mysql_error(&mysql));

        return -1;

    }

    // 执行成功

    // 获取查询的结果集

    MYSQL_RES *result = mysql_store_result(connection);

    if (result == nullptr)//没有查询到结果

    {

        memset(buf, 0, sizeof(buf));

        strcpy(buf, mysql_error(&mysql));

        return -1;

    }

    //获取结果集的行数, static_cast<int>() longlongint类型

    int rowcount = static_cast<int>(mysql_affected_rows(connection));

    //获取结果集的列数

    int fieldcount = static_cast<int>(mysql_field_count(connection));

    //根据SQL语句返回的行列总数,动态的建一个model.

    *p = new QStandardItemModel(rowcount, fieldcount);

    MYSQL_FIELD *field;

    int i = 0;

    int j = 0;

    //遍历列, 设置model的数据头

    for(i = 0;i<fieldcount;i++)

    {

        //获取每一列

        field = mysql_fetch_field(result);

        //QMessageBox::information(nullptr, "", field->name);//显示表字段名称

        //设置model数据表的字段名称

        (*p)->setHeaderData(i, Qt::Horizontal, field->name);

    }

    //二维遍历, 设置model的数据体

    for(i = 0;i<rowcount;i++)

    {

        //获取每一行

        MYSQL_ROW row = mysql_fetch_row(result);

        //遍历列

        for(j = 0;j<fieldcount;j++)

        {

            //显示每一行每一列的数据

            //QMessageBox::information(nullptr, "", row[j]);

            //保存数据到model的数据体

            (*p)->setData((*p)->index(i, j, QModelIndex()), row[j]);

        }

    }

    //释放通过mysql_store_result函数分配的内存空间

    mysql_free_result(result);

    return 0;

}

测试:

1. 打开VM虚拟机, 启动"数据库"服务器

2. 运行程序, 连接mysql数据库

菜单栏 --管理 --登录

3. 登录成功后, 执行SQL查询语句

菜单栏 --数据 --执行脚本

select * from table1;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值