当前位置: 首页 > article >正文

day48


数据库操作


一、QSqlDatabase类


    QSqlDatabase:数据库管理类
主要完成数据库的创建、数据库的打开、关闭等操作
该类中常用函数:
 

1、 QSqlDatabase addDatabase(const QString &type, const QString &connectionName = QLatin1String(defaultConnection))
    功能:为应用程序添加一个数据库,如果数据库不存在则添加,如果数据库存在,则直接构造
    参数:数据库驱动类型
    Driver Type         Description
    QDB2                 IBM DB2
    QIBASE                 Borland InterBase Driver
    QMYSQL                 MySQL Driver
    QOCI                  Oracle Call Interface Driver
    QODBC                 ODBC Driver (includes Microsoft SQL Server)
    QPSQL                 PostgreSQL Driver
    QSQLITE               SQLite version 3 or above
    QSQLITE2              SQLite version 2
    QTDS                 Sybase Adaptive Server
    返回值:返回一个QSqlDatabase类对象
    注意:该函数是静态成员函数,可以不用实例化对象
 
 
2、 bool  contains(const QString &connectionName = QLatin1String(defaultConnection))
    功能:判断某个数据库是否存在
    参数:数据库的名称
    返回值:存在返回真,否则返回假
        
3、bool QSqlDatabase::open()
    功能:打开一个数据库,如果数据库存在则打开,否则创建一个数据库
    参数:无
    返回值:bool类型,成功打开返回true失败返回false
 
4、void QSqlDatabase::setDatabaseName(const QString &name)
    功能:设置数据库的名称
    参数:数据库名称
    返回值:无
 
5、 void close()
    功能:关闭数据库
 


 
二、QSqlQuerry:查询类


能完成对sel语句的执行
该类常用的函数
 

1、bool QSqlQuery::exec(const QString &query)
    功能:执行sql语句,并将结果放入到该类的对象中以便于后期的使用
    参数:要执行的sql语句
    返回值:成功执行返回true,失败返回false
 
2、bool QSqlQuery::next()
    bool QSqlQuery::previous()
    功能:返回下一条或上一条记录
    参数:无
    返回值:bool类型
 
3、QSqlRecord QSqlQuery::record() const
    功能:返回当前查询的记录值
    参数:无
    返回值:QSqlRecord类对象


三、QSqlRecord类


1>    该类用于存储某一条记录的信息
2>    常用函数
 

1、int QSqlRecord::count() const
    功能:返回当前记录的字段的个数
    参数:无
    返回值:字段的个数
 
2、QVariant QSqlRecord::value(int index) const
    功能:返回给定下标的字段的值
    参数:字段的下标
    返回值:给定下标的字段值
    
 
实现:
ui界面

头文件

 

#ifndef WIDGET_H
#define WIDGET_H
 
 
#include <QWidget>
#include<QSqlDatabase>        //数据库管理类
#include<QSqlQuery>            //数据库查询类
#include<QSqlError>            //数据库错误信息类
#include<QSqlRecord>          //数据库记录类
 
 
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_addBtn_clicked();
 
 
    void on_showBtn_clicked();
 
 
private:
    Ui::Widget *ui;
 
 
    QSqlDatabase db;           //使用无参构造,实例化一个数据库管理类对象
 
 
};
#endif // WIDGET_H
 
源文件
Plain Text
自动换行

#include "widget.h"
#include "ui_widget.h"
#include<QMessageBox>
#include<QDebug>
 
 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
 
 
    //当界面被关闭时,断开数据库的连接
    connect(this, &Widget::destroyed, [&](){
        db.close();
    });
 
 
 
 
 
 
    //1、添加数据库
    db = QSqlDatabase::addDatabase("QSQLITE");      //添加的是sqlite3的数据库驱动
 
 
    //2、设置数据库的名称
    db.setDatabaseName("my.db");
 
 
 
 
    //4、打开数据库
    if(!db.open())
    {
        QMessageBox::information(this,"提示","数据库打开失败");
        return;
    }
 
 
    //完成对数据表的创建,需要一个sql语句的执行者
    QSqlQuery querry;           //实例化对象
    //准备sql语句
    QString sql = "create table if not exists Stu(id int, name char, score double);";
    //执行sql语句
    if(!querry.exec(sql))
    {
        QMessageBox::information(this,"提示","数据表创建失败");
        return;
    }
 
 
}
 
 
Widget::~Widget()
{
    delete ui;
}
 
 
//添加信息对应的槽函数
void Widget::on_addBtn_clicked()
{
 
 
 
 
    //1、获取ui界面上的信息
    int ui_id = ui->idEdit->text().toInt();    //id号
    QString ui_name = ui->nameEdit->text();    //name
    double ui_score = ui->scoreEdit->text().toDouble();   //score
 
 
    //判断是否某个数据没有填写
    if(ui_id==0 || ui_name.isEmpty() || ui_score==0)
    {
        QMessageBox::information(this,"提示","请将信息填写完整");
        return;
    }
 
 
    //2、准备sql语句
    QString sql =tr("insert into Stu(id, name, score) values(%1, '%2', %3);").arg(ui_id).arg(ui_name).arg(ui_score);
 
 
    //qDebug()<<sql;
 
 
    //3、准备语句执行者
    QSqlQuery querry;
    if(!querry.exec(sql))
    {
        QMessageBox::information(this,"提示","数据添加失败");
        return;
    }
 
 
 
 
    QMessageBox::information(this,"提示","数据添加成功");
 
 
}
 
 
 
 
//展示信息按钮对应的槽函数
void Widget::on_showBtn_clicked()
{
    ui->tableWidget->clearContents();         //清空表格内容
 
 
    //准备sql语句
    QString sql;
    if(ui->nameEdit->text().isEmpty())
    {
        sql = "select * from Stu;";         //表示查询所有表中信息
    }else
    {
        sql = tr("select * from Stu where name='%1';").arg(ui->nameEdit->text());
    }
    qDebug()<<sql;
 
 
    //准备sql执行者
    QSqlQuery querry;
    if(!querry.exec(sql))
    {
        QMessageBox::information(this,"提示","查询失败");
        qDebug() << "失败原因:"<< querry.lastError().text();
        return;
    }
 
 
    //程序执行至此,查询结果保存在querry类对象中了
    //可以调用该类的成员函数next进行遍历该结果集
    int i = 0;
    while(querry.next())
    {
        //循环中表示,querry指向的任意一条记录
        //可以调用成员函数record函数获取当前指向的记录数据:querry.record
        //querry.record().count():返回当前记录的字段个数
        //querry.record().value(i):表示的是当前记录的下标为i的字段的值
        //qDebug()<<querry.record().value(1).toString();
        //将查询的数据展示到ui界面
        //准备数据容器
        for(int j=0; j<querry.record().count(); j++)
        {
            QTableWidgetItem *item = new QTableWidgetItem(querry.record().value(j).toString());
            //将当前项目设置到 ui界面的(i,j)下标处
            ui->tableWidget->setItem(i,j, item);
        }
 
 
 
 
        i++;            //表示遍历下一行
    }
 
 
}

QSS的基本概念


QSS官方:Qt Style Sheets Reference | Qt Widgets 5.15.8
CSS参考手册:CSS 参考手册
1>    QT的样式表(Qt Style Sheets )是一种强大的机制,用于对QT界面的美化工作,此外还可以通过子类化QStyle实现。Qt样式表的概念、术语和语法很大程度上受到HTML层叠样式表(CSS)的启发,但适应了小部件的世界。
2>    样式表是文本规范,可以使用QApplication::setStyleSheet()在整个应用程序上设置,也可以使用QWidget::setStyleSheet()在特定小部件(及其子部件)上设置。如果在不同的层次上设置了几个样式表,Qt将从所有设置的样式表中派生出有效的样式表。这叫做级联

3>    样式表的语法格式
 

选择器名称
{
    属性名称 :属性值 ;
    属性名称 :属性值 ;
}
 
注意:
1、一个样式由两部分组成:选择器和声明
2、选择器可以是:通配符选择器、组件选择器、类选择器、属性选择器、id选择器、后代选择器、子选择器
3、声明有两部分组成:属性名称和属性值,中间用冒号隔开,多个属性中间用分号隔开
4、属性名称不区分大小写,但是选择器要区分大小写
举个例子:
QPushButton { color: red; background-color: white }


选择器

1 通配选择器
  *  
  匹配所有的控件
2 类型选择器
  QPushButton 
  匹配所有QPushButton和其子类的实例

 

QPushButton {background: gray;}
3 属性选择器
   QPushButton[flat="false"]
   匹配所有flat属性是false的QPushButton实例,注意该属性可以是自定义的属性,不一定非要是类本身具有的属性

 

QPushButton[level='dangerous'] { background: magenta; }
/*openButton->setProperty("level",  "dangerous");*/
4 类选择器
 .QPushButton 
 匹配所有QPushButton的实例,但是并不匹配其子类。这是与CSS中的类选择器不一样的地方,注意前面有一个点号

 

.RedButton { background: magenta; } 
/*openButton->setProperty("class",  "RedButton");
closeButton->setProperty("class", "RedButton");*/
2.5 ID选择器
  #myButton
 匹配所有id为myButton的控件实例,这里的id实际上就是objectName指定的值

 

#openButton, #closeButton { 
background: magenta; 
}
6 后代选择器
   QDialog QPushButton
   所有QDialog容器中包含的QPushButton,不管是直接的还是间接的,中间使用空格隔开
 

QDialog {background: gray;}
/* 设置 QDialog中的 QPushButton 的 QSS */
QDialog QPushButton {    
border: 2px solid magenta;    
border-radius: 10px;    
background: white;    
padding: 2px 15px;}
7 子选择器
  QFrame> QPushButton
   所有QFrame容器下面的QPushButton,其中要求QPushButton的直接父容器是QFrame,注意和后代选择器的区别
中间使用大于号隔开
 

QFrame {background: gray;}QFrame > QPushButton {    border: 2px solid magenta;    border-radius: 10px;    background: white;    padding: 2px 15px;}
8 伪类选择器
选择器:状态 作为选择器,支持 ! 操作符,表示 非。
 

QPushButton:hover { color: white }
QCheckBox:checked { color: white }
QCheckBox:!checked { color: red }

如何设置样式表


设置样式表有三种方式


1    使用ui界面中的设置样式表完成
 

/*  通配符选择器  */
*
{
    background-color:red;
}
 
 
/*  类型选择器  */
QPushButton
{
    background-color:green;
}
 
/*属性选择器*/
QPushButton[flag = 'btn']
{
    background-color:blue;
}
 
/*  Id选择器*/
#toolButton, #pushButton_3, #pushButton
{
    background-color:yellow;
}
 
/*后代选择器*/
QGroupBox QPushButton
{
    background-color:black;
}
 
/*子选择器*/
QGroupBox>QPushButton
{
    background-color:pink;
}
 
/* 伪类选择器*/
#pushButton_2:hover
{
     background-color:purple;
}
 
#pushButton_2:pressed
{
     background-color:red;
}
 
#label
{
    text-decoration: line-through  ;
}
 

 


2    使用QWidget类中的setStyleSheet函数完成


1>    该函数是完成对具体的某个组件进行设置样式表的
2>    使用方式
 

1、准备样式表
2、调用函数完成
 
举个例子:
    //1、准备样式表内容
    QString qss("QPushButton{background-color:red;}");
 
 
    //2、调用组件对应的setStyleSheet函数对具体组件进行设置
    ui->pushButton->setStyleSheet(qss);
    ui->pushButton_2->setStyleSheet(qss);
 
 


3    使用QApplication类中的setStyleSheet函数完成


1>    该函数是对整个界面进行统一设置样式表的
2>    使用格式
 

1、准备样式表
2、调用函数完成
3、该函数是在main函数中调用
 
举例:
    //1、准备样式表
    QString qss("QPushButton{background-color:red;}");
    //2、使用样式表
    a.setStyleSheet(qss);
3>    由于上述使用的方式,对于多组件统一设置样式而言,不方便,所以我们可以将样式表内容,写入到一个qss文件中,通过使用io的操作,将文件中的内容读取后进行设置
main.cpp
 

#include "widget.h"
#include<QFile>
#include <QApplication>
 
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
 
 
    //实例化文件对象
    QFile file(":/myqss.qss");
 
 
    //以只读的形式打开文件
    file.open(QFile::ReadOnly);
 
 
    //读取文件中的样式表内容
    QString qss = file.readAll();
 
 
    //将样式表进行统一设置
    a.setStyleSheet(qss);
 
 
    //关闭文件
    file.close();
 
    Widget w;
    w.show();
    return a.exec();
}
MacOS.qss
 

/*
 * MacOS Style Sheet for QT Applications
 * Author: Jaime A. Quiroga P.
 * Company: GTRONICK
 * Last updated: 25/12/2020, 23:10.
 * Available at: https://github.com/GTRONICK/QSS/blob/master/MacOS.qss
 */
QMainWindow {
    background-color:#ececec;
}
QPushButton, QToolButton, QCommandLinkButton{
    padding: 0 5px 0 5px;
    border-style: solid;
    border-top-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #c1c9cf, stop:1 #d2d8dd);
    border-right-color: qlineargradient(spread:pad, x1:1, y1:0, x2:0, y2:0, stop:0 #c1c9cf, stop:1 #d2d8dd);
    border-bottom-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 #c1c9cf, stop:1 #d2d8dd);
    border-left-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 #c1c9cf, stop:1 #d2d8dd);
    border-width: 2px;
    border-radius: 8px;
    color: #616161;
    font-weight: bold;
    background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 #fbfdfd, stop:0.5 #ffffff, stop:1 #fbfdfd);
}
QPushButton::default, QToolButton::default, QCommandLinkButton::default{
    border: 2px solid transparent;
    color: #FFFFFF;
    background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 #84afe5, stop:1 #1168e4);
}
QPushButton:hover, QToolButton:hover, QCommandLinkButton:hover{
    color: #3d3d3d;
}
QPushButton:pressed, QToolButton:pressed, QCommandLinkButton:pressed{
    color: #aeaeae;
    background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 #ffffff, stop:0.5 #fbfdfd, stop:1 #ffffff);
}
QPushButton:disabled, QToolButton:disabled, QCommandLinkButton:disabled{
    color: #616161;
    background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 #dce7eb, stop:0.5 #e0e8eb, stop:1 #dee7ec);
}
QLineEdit, QTextEdit, QPlainTextEdit, QSpinBox, QDoubleSpinBox, QTimeEdit, QDateEdit, QDateTimeEdit {
    border-width: 2px;
    border-radius: 8px;
    border-style: solid;
    border-top-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 #c1c9cf, stop:1 #d2d8dd);
    border-right-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 #c1c9cf, stop:1 #d2d8dd);
    border-bottom-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 #c1c9cf, stop:1 #d2d8dd);
    border-left-color: qlineargradient(spread:pad, x1:1, y1:0, x2:0, y2:0, stop:0 #c1c9cf, stop:1 #d2d8dd);
    background-color: #f4f4f4;
    color: #3d3d3d;
}
QLineEdit:focus, QTextEdit:focus, QPlainTextEdit:focus, QSpinBox:focus, QDoubleSpinBox:focus, QTimeEdit:focus, QDateEdit:focus, QDateTimeEdit:focus {
    border-width: 2px;
    border-radius: 8px;
    border-style: solid;
    border-top-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 #85b7e3, stop:1 #9ec1db);
    border-right-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 #85b7e3, stop:1 #9ec1db);
    border-bottom-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 #85b7e3, stop:1 #9ec1db);
    border-left-color: qlineargradient(spread:pad, x1:1, y1:0, x2:0, y2:0, stop:0 #85b7e3, stop:1 #9ec1db);
    background-color: #f4f4f4;
    color: #3d3d3d;
}
QLineEdit:disabled, QTextEdit:disabled, QPlainTextEdit:disabled, QSpinBox:disabled, QDoubleSpinBox:disabled, QTimeEdit:disabled, QDateEdit:disabled, QDateTimeEdit:disabled {
    color: #b9b9b9;
}
QSpinBox::up-button, QDoubleSpinBox::up-button, QTimeEdit::up-button, QDateEdit::up-button, QDateTimeEdit::up-button {
    subcontrol-origin: padding;
    subcontrol-position: top right;
    width: 15px;
    color: #272727;
    border-left-width: 1px;
    border-left-color: darkgray;
    border-left-style: solid;
    border-top-right-radius: 3px;
    padding: 3px;
}
QSpinBox::down-button, QDoubleSpinBox::down-button, QTimeEdit::down-button, QDateEdit::down-button, QDateTimeEdit::down-button {
    subcontrol-origin: padding;
    subcontrol-position: bottom right;
    width: 15px;
    color: #272727;
    border-left-width: 1px;
    border-left-color: darkgray;
    border-left-style: solid;
    border-bottom-right-radius: 3px;
    padding: 3px;
}
QSpinBox::up-button:pressed, QDoubleSpinBox::up-button:pressed, QTimeEdit::up-button:pressed, QDateEdit::up-button:pressed, QDateTimeEdit::up-button:pressed {
    color: #aeaeae;
    background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 #ffffff, stop:0.5 #fbfdfd, stop:1 #ffffff);
}
QSpinBox::down-button:pressed, QDoubleSpinBox::down-button:pressed, QTimeEdit::down-button:pressed, QDateEdit::down-button:pressed, QDateTimeEdit::down-button:pressed {
    color: #aeaeae;
    background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 #ffffff, stop:0.5 #fbfdfd, stop:1 #ffffff);
}
QSpinBox::up-button:hover, QDoubleSpinBox::up-button:hover, QTimeEdit::up-button:hover, QDateEdit::up-button:hover, QDateTimeEdit::up-button:hover {
    color: #FFFFFF;
    border-top-right-radius: 5px;
    background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 #84afe5, stop:1 #1168e4);
 
 
}
QSpinBox::down-button:hover, QDoubleSpinBox::down-button:hover, QTimeEdit::down-button:hover, QDateEdit::down-button:hover, QDateTimeEdit::down-button:hover {
    color: #FFFFFF;
    border-bottom-right-radius: 5px;
    background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 #84afe5, stop:1 #1168e4);
}
QSpinBox::up-arrow, QDoubleSpinBox::up-arrow, QTimeEdit::up-arrow, QDateEdit::up-arrow, QDateTimeEdit::up-arrow {
    image: url(/usr/share/icons/Adwaita/16x16/actions/go-up-symbolic.symbolic.png);
}
QSpinBox::down-arrow, QDoubleSpinBox::down-arrow, QTimeEdit::down-arrow, QDateEdit::down-arrow, QDateTimeEdit::down-arrow {
    image: url(/usr/share/icons/Adwaita/16x16/actions/go-down-symbolic.symbolic.png);
}
QProgressBar {
    max-height: 8px;
    text-align: center;
    font: italic bold 11px;
    color: #3d3d3d;
    border: 1px solid transparent;
    border-radius:4px;
    background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #ddd5d5, stop:0.5 #dad3d3, stop:1 #ddd5d5);
}
QProgressBar::chunk {
    background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #467dd1, stop:0.5 #3b88fc, stop:1 #467dd1);
    border-radius: 4px;
}
QProgressBar:disabled {
    color: #616161;
}
QProgressBar::chunk:disabled {
    background-color: #aeaeae;
}
QSlider::groove {
    border: 1px solid #bbbbbb;
    background-color: #52595d;
    border-radius: 4px;
}
QSlider::groove:horizontal {
    height: 6px;
}
QSlider::groove:vertical {
    width: 6px;
}
QSlider::handle:horizontal {
    background: #ffffff;
    border-style: solid;
    border-width: 1px;
    border-color: rgb(207,207,207);
    width: 12px;
    margin: -5px 0;
    border-radius: 7px;
}
QSlider::handle:vertical {
    background: #ffffff;
    border-style: solid;
    border-width: 1px;
    border-color: rgb(207,207,207);
    height: 12px;
    margin: 0 -5px;
    border-radius: 7px;
}
QSlider::add-page, QSlider::sub-page {
    border: 1px transparent;
    background-color: #52595d;
    border-radius: 4px;
}
QSlider::add-page:horizontal {
    background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #ddd5d5, stop:0.5 #dad3d3, stop:1 #ddd5d5);
}
QSlider::sub-page:horizontal {
    background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 #467dd1, stop:0.5 #3b88fc, stop:1 #467dd1);
}
QSlider::add-page:vertical {
    background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #467dd1, stop:0.5 #3b88fc, stop:1 #467dd1);
}
QSlider::sub-page:vertical {
    background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 #ddd5d5, stop:0.5 #dad3d3, stop:1 #ddd5d5);
}
QSlider::add-page:horizontal:disabled, QSlider::sub-page:horizontal:disabled, QSlider::add-page:vertical:disabled, QSlider::sub-page:vertical:disabled {
    background: #b9b9b9;
}
QComboBox, QFontComboBox {
    border-width: 2px;
    border-radius: 8px;
    border-style: solid;
    border-top-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 #c1c9cf, stop:1 #d2d8dd);
    border-right-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 #c1c9cf, stop:1 #d2d8dd);
    border-bottom-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 #c1c9cf, stop:1 #d2d8dd);
    border-left-color: qlineargradient(spread:pad, x1:1, y1:0, x2:0, y2:0, stop:0 #c1c9cf, stop:1 #d2d8dd);
    background-color: #f4f4f4;
    color: #272727;
    padding-left: 5px;
}
QComboBox:editable, QComboBox:!editable, QComboBox::drop-down:editable, QComboBox:!editable:on, QComboBox::drop-down:editable:on {
    background: #ffffff;
}
QComboBox::drop-down {
    subcontrol-origin: padding;
    subcontrol-position: top right;
    width: 15px;
    color: #272727;
    border-left-width: 1px;
    border-left-color: darkgray;
    border-left-style: solid;
    border-top-right-radius: 3px;
    border-bottom-right-radius: 3px;
}
QComboBox::down-arrow {
    image: url(/usr/share/icons/Adwaita/16x16/actions/go-down-symbolic.symbolic.png); /*Adawaita icon thene*/
}
 
 
QComboBox::down-arrow:on {
    top: 1px;
    left: 1px;
}
QComboBox QAbstractItemView {
    border: 1px solid darkgray;
    border-radius: 8px;
    selection-background-color: #dadada;
    selection-color: #272727;
    color: #272727;
    background: white;
}
QLabel, QCheckBox, QRadioButton {
    color: #272727;
}
QCheckBox {
    padding: 2px;
}
QCheckBox:disabled, QRadioButton:disabled {
    color: #808086;
    padding: 2px;
}
 
 
QCheckBox:hover {
    border-radius:4px;
    border-style:solid;
    padding-left: 1px;
    padding-right: 1px;
    padding-bottom: 1px;
    padding-top: 1px;
    border-width:1px;
    border-color: transparent;
}
QCheckBox::indicator:checked {
    image: url(/usr/share/icons/Adwaita/16x16/actions/object-select-symbolic.symbolic.png);
    height: 15px;
    width: 15px;
    border-style:solid;
    border-width: 1px;
    border-color: #48a5fd;
    color: #ffffff;
    border-radius: 3px;
    background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #48a5fd, stop:0.5 #329cfb, stop:1 #48a5fd);
}
QCheckBox::indicator:unchecked {
 
 
    height: 15px;
    width: 15px;
    border-style:solid;
    border-width: 1px;
    border-color: #48a5fd;
    border-radius: 3px;
    background-color: #fbfdfa;
}
QLCDNumber {
    color: #616161;;
}
QMenuBar {
    background-color: #ececec;
}
QMenuBar::item {
    color: #616161;
    spacing: 3px;
    padding: 1px 4px;
    background-color: #ececec;
}
 
 
QMenuBar::item:selected {
    background-color: #dadada;
    color: #3d3d3d;
}
QMenu {
    background-color: #ececec;
}
QMenu::item:selected {
    background-color: #dadada;
    color: #3d3d3d;
}
QMenu::item {
    color: #616161;;
    background-color: #e0e0e0;
}
QTabWidget {
    color:rgb(0,0,0);
    background-color:#000000;
}
QTabWidget::pane {
    border-color: #050a0e;
    background-color: #e0e0e0;
    border-width: 1px;
    border-radius: 4px;
    position: absolute;
    top: -0.5em;
    padding-top: 0.5em;
}
 
 
QTabWidget::tab-bar {
    alignment: center;
}
 
 
QTabBar::tab {
    border-bottom: 1px solid #c0c0c0;
    padding: 3px;
    color: #272727;
    background-color: #fefefc;
    margin-left:0px;
}
QTabBar::tab:!last {
    border-right: 1px solid;
    border-right-color: #c0c0c0;
    border-bottom-color: #c0c0c0;
}
QTabBar::tab:first {
    border-top-left-radius: 4px;
    border-bottom-left-radius: 4px;
}
QTabBar::tab:last {
    border-top-right-radius: 4px;
    border-bottom-right-radius: 4px;
}
QTabBar::tab:selected, QTabBar::tab:last:selected, QTabBar::tab:hover {
    color: #FFFFFF;
    background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 #84afe5, stop:1 #1168e4);
}
QRadioButton::indicator {
    height: 14px;
    width: 14px;
    border-style:solid;
    border-radius:7px;
    border-width: 1px;
}
QRadioButton::indicator:checked {
    border-color: #48a5fd;
    background-color: qradialgradient(cx:0.5, cy:0.5, radius:0.4,fx:0.5, fy:0.5, stop:0 #ffffff, stop:0.5 #ffffff, stop:0.6 #48a5fd, stop:1 #48a5fd);
}
QRadioButton::indicator:!checked {
    border-color: #a9b7c6;
    background-color: #fbfdfa;
}
QStatusBar {
    color:#027f7f;
}
 
 
QDial {
    background: #16a085;
}
 
 
QToolBox {
    color: #a9b7c6;
    background-color: #222b2e;
}
QToolBox::tab {
    color: #a9b7c6;
    background-color:#222b2e;
}
QToolBox::tab:selected {
    color: #FFFFFF;
    background-color:#222b2e;
}
QScrollArea {
    color: #FFFFFF;
    background-color:#222b2e;
}
 
 
QScrollBar:horizontal {
        max-height: 10px;
        border: 1px transparent grey;
        margin: 0px 20px 0px 20px;
        background: transparent;
}
QScrollBar:vertical {
        max-width: 10px;
        border: 1px transparent grey;
        margin: 20px 0px 20px 0px;
        background: transparent;
}
QScrollBar::handle:vertical, QScrollBar::handle:horizontal {
        background: #52595d;
        border-style: transparent;
        border-radius: 4px;
        min-height: 25px;
}
QScrollBar::handle:horizontal:hover, QScrollBar::handle:vertical:hover {
        background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 #467dd1, stop:0.5 #3b88fc, stop:1 #467dd1);
}
QScrollBar::add-line, QScrollBar::sub-line {
    border: 2px transparent grey;
    border-radius: 4px;
    subcontrol-origin: margin;
    background: #b9b9b9;
}
QScrollBar::add-line:horizontal {
    width: 20px;
    subcontrol-position: right;
}
QScrollBar::add-line:vertical {
    height: 20px;
    subcontrol-position: bottom;
}
QScrollBar::sub-line:horizontal {
    width: 20px;
    subcontrol-position: left;
}
QScrollBar::sub-line:vertical {
    height: 20px;
    subcontrol-position: top;
}
QScrollBar::add-line:vertical:pressed, QScrollBar::add-line:horizontal:pressed, QScrollBar::sub-line:horizontal:pressed, QScrollBar::sub-line:vertical:pressed {
    background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 #467dd1, stop:0.5 #3b88fc, stop:1 #467dd1);
}
QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal, QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
    background: none;
}
QScrollBar::up-arrow:vertical {
    image: url(/usr/share/icons/Adwaita/16x16/actions/go-up-symbolic.symbolic.png);
}
QScrollBar::down-arrow:vertical {
    image: url(/usr/share/icons/Adwaita/16x16/actions/go-down-symbolic.symbolic.png);
}
QScrollBar::left-arrow:horizontal {
    image: url(/usr/share/icons/Adwaita/16x16/actions/go-previous-symbolic.symbolic.png);
}
QScrollBar::right-arrow:horizontal {
    image: url(/usr/share/icons/Adwaita/16x16/actions/go-next-symbolic.symbolic.png);
}
 

opencv的使用


一、关于计算机视觉的相关基础


1>    Opencv:开源的计算机视觉
2>    能够完成对图像的细致操作,例如对像素的操作,需要使用第三方库,opencv库
3>    该库在图像识别领域,已经做到佼佼者了,QT在图形化界面已经做到佼佼者了
4>    配置opencv库
 


 
二、opencv基本类的介绍


2.1    关于图像处理的相关类和函数


1>    Mat类,图像容器
2>    读取图像
 

Mat imread( const String& filename, int flags = IMREAD_COLOR );
//功能:读取出图像
    //参数:图像路径
    //返回值:读取的图像
3>    命名展示图像的窗口
 

void namedWindow(const String& winname, int flags = WINDOW_AUTOSIZE);
功能:命名一个图像窗口
参数1:窗口名称
参数2:窗体尺寸,默认为自适应大小
返回值:无
 
4>    展示图像
 

void imshow(const String& winname, const ogl::Texture2D& tex);
    //功能:展示图像
    //参数1:要展示图像的窗口名称
    //参数2:要展示的二维图像
    //返回值:无
案例
 

#include "widget.h"
#include <QApplication>
 
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
 
 
    //1、定义一个图像容器
    Mat src;
 
 
    //2、将图像加载进来
    //函数原型:Mat imread( const String& filename, int flags = IMREAD_COLOR );
    //参数:图像的路径
    //返回值:图像容器
    src = imread("D:/opencv/resource/age.jpg");
 
 
    //4、命名一个展示图像的窗口
    //namedWindow("Test");
 
 
    //5、展示图像
    //函数原型:void imshow(const String& winname, const ogl::Texture2D& tex);
    //参数1:要展示图像的窗口名称
    //参数2:要展示的图像
    //返回值:无
    imshow("Test", src);
 
 
 
 
    return a.exec();
}
 
 


2.2    视频流相关类和函数


1>    视频流类:VideoCapture
2>    打开视频:
 

 virtual bool open(const String& filename);
    //参数:要打开视频的路径
    //返回值:成功返回true失败返回false
3>    打开摄像头只需在构造时,调用构造函数参数传递0即可
4>    读取视频流中图像
 

virtual bool read(OutputArray image);
功能:读取视频流中的图像
参数:图像容器
返回值:成功读取返回true,失败或者视频结束返回false
4>    图像翻转
 

void flip(InputArray src, OutputArray dst, int flipCode);
        //将图像进行旋转
        //参数1:要处理的图像
        //参数2:处理后的图像容器
        //参数3:处理规则:0:表示沿x翻转,1表示沿y轴翻转,-1表示沿xy轴翻转
5>    休眠阻塞函数
 

int waitKey(int delay = 0);
功能:阻塞等待用户输入数据,如果delay=0,则一直等待
参数:毫秒数
返回值:在等待过程中用户按下键的值
案例:
 

#include "widget.h"
#include "ui_widget.h"
 
 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
 
 
    //1、实例化一个视频容器的对象
    VideoCapture video;
 
 
    //2、使用类中成员函数,打开给定路径的视频
    if(!video.open(0))
    {
        QMessageBox::information(this, "提示", "视频打开失败");
        return ;
    }
 
 
    //3、从视频流中,将每一张图像读取出来
    Mat src;            //定义图像容器,用于读取视频中的额图像
    namedWindow("test");       //命名一个窗口用于展示图像
 
 
    //循环读取视频中的图像
    while(video.read(src))
    {
        //将图像镜像翻转一下
        flip(src, src, 1);
 
 
        //src中存储了视频中的任意一张图像
        //将图像展示到命名的窗口中
        imshow("test", src);
 
 
        if(waitKey(20) == 27)        //说明用户按下了ESC键
        {
            break;
        }
 
 
    }
 
 
 
 
}
 
 
Widget::~Widget()
{
    delete ui;
}
 
 
 
 


2.3    图像处理


1>    灰度处理
 

void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
功能:转换图像色彩空间
//参数1:要转换的图像
//参数2:转变后图像容器
//参数3:转换规则:BGR to gray
返回值:无
2>    均衡化处理
 

void equalizeHist( InputArray src, OutputArray dst ); 
参数1:输入的灰度图像,必须是8-bit的单通道图像  
参数2:输出的图像 
图像直方图:对整个图像在灰度范围内的像素值(0-255)统计出现的频率,据此生成直方图,直 方图反应了图像的灰度分布情况。
案例:
 

#include "widget.h"
#include <QApplication>
 
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
 
 
    //1、定义视频流对象
    VideoCapture v(0);             //表明使用摄像头构造一个视频流对象
 
 
    //2、读取摄像头中的图像
    Mat src;                   //用于存放读取出来的图像
    Mat gray;                   //用于存储灰度图的图像容器
    Mat dst;                     //用于存储均衡化处理后的图像容器
 
 
    //函数原型:virtual bool read(OutputArray image);
    //功能:从视频流中读取一张图像放入参数中
    //参数:图像容器
    //返回值:成功返回真,失败或者读取视频结束返回假
    while(v.read(src))
    {
        //将图像进行翻转
        //函数原型:void flip(InputArray src, OutputArray dst, int flipCode);
        //参数1:要翻转的图像
        //参数2:翻转后的图像容器
        //参数3:翻转规则:正数表示按y轴翻转,0表示按x轴翻转,负数表示按xy轴翻转
        flip(src, src, 1);
 
 
        //3、将图像灰度处理
        //函数原型:void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
        //参数1:要转换的图像
        //参数2:转换后的图像容器
        //参数3:转换规则  CV_BGR2GRAY表示将bgr彩色图转换为gray灰度图
        //返回值:无
        cvtColor(src, gray, CV_BGR2GRAY);
 
 
        //4、对图像进行均衡化处理
        //函数原型:void equalizeHist( InputArray src, OutputArray dst );
        //参数1:要进行均衡化处理的图像,必须是单通道灰度图
        //参数2:均衡化处理后的图像容器
        //返回值:无
        equalizeHist(gray, dst);
 
 
        //展示彩色图像
        imshow("Test1", src);
 
 
        //展示灰度图像
        imshow("Test2", gray);
 
 
        //展示均衡化处理后的图像
        imshow("Test3", dst);
 
 
        //加延时函数
        //函数原型:int waitKey(int delay = 0);
        //参数:等待时间
        //返回值:在等待期间用户按下的键盘的ascii值    ESC键对应的值为27
        if(waitKey(20)==27)
        {
            break;
        }
    }
 
 
 
 
 
 
    return a.exec();
}
 
 


2.4    级联分类器


1>    opencv级联分类器工具类 : CascadeClassifier  //struct Student 
2>    加载级联分类器配置文件 : bool load( const String& filename ) 
参数1:分类器数据文件的名字 
返回值:成功true,失败false 
3>    找到人脸所在位置的矩形区域
 

void detectMultiScale(
 const Mat& image, 
CV_OUT vector& objects,    //int arr[4]; 
double scaleFactor = 1.1,
int minNeighbors = 3, 
int flags = 0, 
Size ize = Size(24,24))
参数1:待检测灰度图像(数据少处理起来简单) 
参数2:被检测物体的矩形框向量( 人脸Rect矩形区域,其中objects.size()是人脸个数 ) 
参数3:前后两次相继的扫描中搜索窗口的比例系数,默认为1.1 即每次搜索窗口扩大10% 
参数4:构成检测目标的相邻矩形的最小个数 如果组成检测目标的小矩形的个数和小于 minneighbors - 1 都会被除 
参数5:若设置为CV_HAAR_DO_CANNY_PRUNING 函数将会使用Canny边缘检测来排除边缘过多 或过少的区域,,一般采用默认值0 
参数6:用来限制得到的目标区域的范围,一般检测人脸使用Size(24, 24)
4>    人脸部分的矩形区域显示出来
 

void rectangle(CV_IN_OUT Mat& img, Rect rec,
                          const Scalar& color, int thickness = 1,
                          int lineType = LINE_8, int shift = 0);
img:图像。 
rec:表征矩形的位置和长宽。 
color:线条颜色 (RGB) 。 
thickness:组成矩形的线条的粗细程度。 
line_type:线条的类型。 
shift:坐标点的小数点位数,0表示没有小数点。
 
案例实现
1>    配置文件pro
 

QT       += core gui
 
 
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 
 
CONFIG += c++11
 
 
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
 
 
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
 
 
SOURCES += \
    main.cpp \
    widget.cpp
 
 
HEADERS += \
    widget.h
 
 
FORMS += \
    widget.ui
 
 
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
 
 
 
 
 
 
INCLUDEPATH += D:/opencv/opencv3.4-qt-intall/install/include
INCLUDEPATH += D:/opencv/opencv3.4-qt-intall/install/include/opencv
INCLUDEPATH += D:/opencv/opencv3.4-qt-intall/install/include/opencv2
LIBS += D:/opencv/opencv3.4-qt-intall/install/x86/mingw/lib/libopencv_*.a
 
 
2>    头文件
 

#ifndef WIDGET_H
#define WIDGET_H
 
 
#include <QWidget>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
#include<opencv2/face.hpp>
#include <vector>
#include <map>
#include <QMessageBox>
#include <QDebug>
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QTimerEvent>
 
 
using namespace  cv;
using namespace cv::face;
using namespace std;
 
 
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
 
 
class Widget : public QWidget
{
    Q_OBJECT
 
 
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
 
 
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H
 
 
3>    源文件
 

#include "widget.h"
#include "ui_widget.h"
 
 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
 
 
    //1、准备相关容器
    Mat src;           //用于存储图像
    Mat gray;           //用于存储灰度图
    Mat dest;          //用于存储均衡化图像
    VideoCapture video;    //视频流对象,用于存储视频数据
    CascadeClassifier c;    //定义级联分类器对象
    vector<Rect> faces;     //用于存储图像的人脸矩形区域
 
 
    //给级联分类器装载模型
    //函数原型:bool load( const String& filename );
    //参数:级联分类器模型,此处使用的是人脸分类模型
    //返回值:成功下载返回值真,否则返回假
    if(!c.load("D:/opencv/resources/haarcascade_frontalface_alt2.xml"))
    {
        QMessageBox::information(this, "提示", "人脸分类模型下载失败");
        return;
    }
 
 
    //2、加载视频到对象中来
    //函数原型:bool open(String  fileNmae);
    //功能:打开本地磁盘上的某个文件
    //参数:文件路径
    //返回值:成功打开返回真,否则返回假
    if(!video.open(0))
    {
        QMessageBox::information(this, "提示","视频打开失败");
        return;
    }
 
 
    //程序执行至此,表示类 对象中包含了视频
    while(video.read(src))
    {
        //此时src中读取了一张图像
        //将图像进行翻转
        //函数原型:void flip(InputArray src, OutputArray dst, int flipCode);
        //参数1:要翻转的图像
        //参数2:翻转后的图像容器
        //参数3:翻转码:0表示按x轴翻转,正值表示按y轴翻转,负值表示两个轴都翻转
        flip(src, src, 1);
 
 
        /*src.at<cv::Vec3b>(i,j):表示该图像中的任意一个像素点,都是3字节组成
        for(int i=0; i<src.rows; i++)          //外层循环遍历行
        {
            for(int j=0; j<src.cols; j++)        //内层循环遍历列数
            {
                //遍历当前像素的每一个颜色值
                for(int k=0; k<3; k++)
                {
                    src.at<cv::Vec3b>(i,j)[k] = 255 - src.at<cv::Vec3b>(i,j)[k];   //获取该颜色的反差值
                }
            }
        }*/
 
 
        //灰度处理
        //函数原型:void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
        //参数1:要处理的原图像
        //参数2:色彩空间转换后的图像容器
        //参数3:转换规则:CV_BGR2GRAY表示将BGR图转变成灰度图
        cv::cvtColor(src, gray, CV_BGR2GRAY);
 
 
        //均衡化处理
        //函数原型:void equalizeHist( InputArray src, OutputArray dst );
        //参数1:要被处理的图像
        //参数2:均衡化处理后的图像容器
        cv::equalizeHist(gray, dest);
 
 
        //从灰度图中通过级联分类器获取人脸矩形区域
        c.detectMultiScale(dest, faces);
        //参数1:要被识别的图像
        //参数2:存储图像上的人脸矩形区域的容器
 
 
        //遍历矩形框数组,将所有的矩形框都绘制到指定图像上
        for(int i=0; i<faces.size(); i++)
        {
            //该循环中找到任意一个矩形框 faces[i]
            cv::rectangle(src, faces[i], Scalar(0,0,255), 2);
            //参数1:要绘制矩形框的图像
            //参数2:要被绘制的矩形框
            //参数3:矩形框颜色
            //参数4:矩形框的粗细
        }
 
 
 
 
        //展示图像
        imshow("src", src);
        imshow("gray", gray);
        imshow("dest", dest);
 
 
        //调用延时函数
        if(waitKey(30) == 27)
        {
            //如果用户按下了ESC,可以结束循环
            break;
        }
    }
 
 
}
 
 
Widget::~Widget()
{
    delete ui;
}
 
 
 
 
 


三、人脸识别器


3.1    介绍


机器学习的作用:根据提供的图片模型通过算法生成数据模型,从而在其它图片中查找相关的目 标。
级联分类器:是用来人脸识别。 在判断之前,我们要先进行学习,生成人脸的模型以便后续识别使用。 
人脸识别器:判断是谁的面部。 FaceRecognizer类是opencv提供的人脸识别器基类,LBPHFaceRecognizer是根据LBPH算法实 现的识别器类,其中LBPHFaceRecognizer识别器支持在原有模型基础上继续学习(模型数据可以累 计)。


3.2    创建LBPHFaceRecognizer识别器对象
 

 所需的头文件:#include 、using namespace cv::face;
 创建空的人脸识别器对象:Ptr<FaceRecognizer> recognizer =
 LBPHFaceRecognizer::create();
 ​
 根据已有的模型创建人脸识别器对象,在创建人脸识别器的时候,需要一个已经学习好的模型文件:
 Ptr<FaceRecognizer> recognizer = FaceRecognizer::load<LBPHFaceRecognizer>("模型文件.xml");


3.3    机器学习并更新模型
 

 容器:容器中装了n张人脸Mat对象,先采集脸,装到容器中,存储标签,人的身份证,每一张脸
 给一个编号:1 张三脸 2 李四脸 3 王五脸。
 功能函数1:void update(InputArrayOfArray src,InputArray labels)//机器学习并更新模型
 功能函数2:void train(InputArrayOfArrays src,InputArray labels);//只是学习,不更新
 //参数1src:图片模型数组 vector<Mat>
 //参数2labels:标签数组,每个模型识别后的标签vector<int>


3.4    保存模型
 

 功能函数:void save(const String& filename);//参数1:模型文件的名字
 例如:
 recognizer->update(study_faces,study_label);//学习
 recognizer->save("face.xml");//将学习的成果,保存到face.xml模型文件中,生成模型:
 study_faces.clear();、study_labels.clear();


3.5    预测目标
 

 判断这个人脸到底是谁。
 功能函数:
 void predict(InputArray src,  int &label,  double &confidence)
 //参数1:预测图形 Mat src
 //参数2::预测后的标签,学习时对应的标签
 //参数3:预测出结果的可信度,数值越小可信度越高
 例如:
 int label = -1;//预测后的标签,学习时对应的标签
 double confidence = 0;//可信度
 Mat face = frame(faces[0]);//人脸区域
 cvtColor(face,face,CV_BGR2GRAY);//更改色彩空间
 cv::resize(face,face,Size(90,90));//设置人脸的大小
 recognizer->predict(face,label,confidence); //预测,相当于识别人脸,预测出人脸是谁的
 面部,label的值就那张脸对应的标签,如果预测不到,label的值是-1。
 ​


3.6    设置可信度
 

 功能函数:void setThreshold(double val);
 //参数1:预测可信度极值,预测可信度超出极值则预测失败。
 ​


3.7    项目总汇


1>    ui界面

2>    配置文件
 

QT       += core gui
 
 
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 
 
CONFIG += c++11
 
 
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
 
 
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
 
 
SOURCES += \
    main.cpp \
    widget.cpp
 
 
HEADERS += \
    widget.h
 
 
FORMS += \
    widget.ui
 
 
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
 
 
INCLUDEPATH += D:/opencv/opencv3.4-qt-intall/install/include
INCLUDEPATH += D:/opencv/opencv3.4-qt-intall/install/include/opencv
INCLUDEPATH += D:/opencv/opencv3.4-qt-intall/install/include/opencv2
LIBS += D:/opencv/opencv3.4-qt-intall/install/x86/mingw/lib/libopencv_*.a
 
 
3>    头文件
 

#ifndef WIDGET_H
#define WIDGET_H
 
 
#include <QWidget>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
#include<opencv2/face.hpp>
#include <vector>
#include <map>
#include <QMessageBox>
#include <QDebug>
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QTimerEvent>
 
 
using namespace  cv;
using namespace cv::face;
using namespace std;
 
 
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
 
 
class Widget : public QWidget
{
    Q_OBJECT
 
 
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
 
 
    //重写定时器事件处理函数
    void timerEvent(QTimerEvent *e);
 
 
private slots:
    void on_openCameraBtn_clicked();
 
 
    void on_closeCameraBtn_clicked();
 
 
 
 
    void on_inputFaceBtn_clicked();
 
 
    void on_faceLoginBtn_clicked();
 
 
private:
    Ui::Widget *ui;
 
 
    /************定义有关摄像头的相关变量*********************/
    Mat src;           //用于存储图像
    Mat rgb;            //存储rgb图像
    Mat gray;           //用于存储灰度图
    Mat dest;          //用于存储均衡化图像
    VideoCapture video;    //视频流对象,用于存储视频数据
    CascadeClassifier c;    //定义级联分类器对象
    vector<Rect> faces;     //用于存储图像的人脸矩形区域
    int cameraTimerId;       //展示摄像头的定时器id号
 
 
    /*****************定义有关人脸录入的相关变量***************/
    Ptr<FaceRecognizer> recognizer;           //人脸识别器
    vector<Mat> input_faces;                  //要进行人脸训练的脸的容器
    vector<int> input_labs;                   //没张脸对应的编号
    int inputTimerId;                         //人脸录入的定时器
 
 
    /******************定义有关人脸登录的变量*****************/
    int faceLoginTimerId;            //人脸登录的定时器
 
 
 
 
 
 
 
 
};
#endif // WIDGET_H
4>    源文件
 

#include "widget.h"
#include "ui_widget.h"
 
 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
 
 
    //关闭摄像头按钮设置禁用
    ui->closeCameraBtn->setEnabled(false);
 
 
    //给级联分类器装载模型
    //函数原型:bool load( const String& filename );
    //参数:级联分类器模型,此处使用的是人脸分类模型
    //返回值:成功下载返回值真,否则返回假
    if(!c.load("D:/opencv/resources/haarcascade_frontalface_alt2.xml"))
    {
        QMessageBox::information(this, "提示", "人脸分类模型下载失败");
        return;
    }
 
 
}
 
 
Widget::~Widget()
{
    delete ui;
}
 
 
//定时器事件处理函数的定义
void Widget::timerEvent(QTimerEvent *e)
{
    //判断是否为打开摄像头的定时器到位
    if(e->timerId() == cameraTimerId)
    {
        //从视频流中获取一张图像
        video.read(src);
 
 
        //将图像进行翻转
        flip(src, src,1);
 
 
        //将原图像转变成rgb图
        cvtColor(src, rgb, CV_BGR2RGB);
 
 
        //将rgb图重新设置尺寸,以便于能够放入ui界面的标签中
        cv::resize(rgb, rgb, Size(300,300));
 
 
        //将图像进行灰度处理
        cvtColor(rgb, gray, CV_BGR2GRAY);
 
 
        //均衡化处理
        cv::equalizeHist(gray, dest);
 
 
        //从均衡化图像中获取矩形区域
        c.detectMultiScale(dest, faces);
        //将矩形框绘制到原图上 rgb
        for(uint i=0; i<faces.size(); i++)
        {
            rectangle(rgb, faces[i], Scalar(0,0,255), 2);
        }
 
 
        //imshow("test", rgb);
        //通过rgb的Mat图像,先构造一个QImage图像
        QImage image = QImage(rgb.data,             //其他图像的数据起始地址
                              rgb.cols,             //其他图像的总列数也就是宽度
                              rgb.rows,             //其他图像的总函数,也就是高度
                              rgb.cols*rgb.channels(),   //其他图像每一行的字节个数 总列数*通道数
                              QImage::Format_RGB888);    //转换的格式,24位图,分别每种颜色占一字节
        //可以通过QImage图转换为QPixmap图,只需要调用静态成员函数fromImage
        QPixmap pix = QPixmap::fromImage(image);
 
 
        //将图像展示到ui界面
        ui->cameraLab->setPixmap(pix);
    }
 
 
 
 
    //判断是否为人脸录入定时器到位
    if(e->timerId() == inputTimerId)
    {
        qDebug() << "人脸录入中,请稍后....";
        //判断摄像头中是否有人脸
        if(faces.empty())        //没有人脸矩形框
        {
            return;
        }
 
 
        //将图像中的人脸矩形区域抠出来
        Mat face = src(faces[0]);
 
 
        //将图像重新设置大小
        cv::resize(face, face, Size(100,100));
 
 
        //灰度处理
        cvtColor(face,face, CV_BGR2GRAY);
 
 
        //均衡化处理
        equalizeHist(face,face);
 
 
        //将该图像放入到输入容器中
        input_faces.push_back(face);
        input_labs.push_back(1);
 
 
        //判断是否集齐了50张脸
        if(input_faces.size()==50)
        {
            //更新模型
            recognizer->update(input_faces, input_labs);
            //将该模型保存到本地磁盘上
            recognizer->save("D:/opencv/resources/myface.xml");
 
 
            //后续操作
            //将容器清空,以便于后面的人脸录入
            input_labs.clear();
            input_faces.clear();
 
 
            //关闭定时器
            this->killTimer(inputTimerId);
            //将关闭摄像头按钮启用
            ui->closeCameraBtn->setEnabled(true);
 
 
            QMessageBox::information(this, "提示","录入成功");
        }
    }
 
 
 
 
    //判断是否为人脸登录定时器到位
    if(e->timerId() == faceLoginTimerId)
    {
        qDebug()<<"正在登录,请稍后.....";
        //判断是否有人脸
        if(faces.empty() || recognizer.empty())
        {
            return;
        }
 
 
        //获取ui界面中人脸区域
        Mat face = src(faces[0]);
 
 
        //重新设置尺寸
        cv::resize(face,face,Size(100,100));
 
 
        //灰度处理
        cvtColor(face,face,CV_BGR2GRAY);
 
 
        //均衡化处理
        equalizeHist(face,face);
 
 
        //准备两个产出数据
        int out_lab = -1;
        double out_conf = 0.0;
 
 
        //调用预测函数
        recognizer->predict(face, out_lab, out_conf);
        qDebug()<<"out_lab = "<<out_lab<<"     out_conf = "<<out_conf;
 
 
        if(out_lab != -1)
        {
            QMessageBox::information(this, "提示", "欢迎回来");
 
 
            //关闭定时器
            killTimer(faceLoginTimerId);
            //将组件设置成可用
            ui->closeCameraBtn->setEnabled(true);        //禁用关闭摄像头功能
            ui->faceLoginBtn->setEnabled(true);      //设置人脸登录按钮禁用
            ui->inputFaceBtn->setEnabled(true);        //禁用人脸录入功能
 
 
            //当前界面关闭,发送信号给其他界面展示
            
 
 
        }
 
 
    }
}
 
 
//打开摄像头按钮对应的槽函数
void Widget::on_openCameraBtn_clicked()
{
    //2、加载视频到对象中来
    //函数原型:bool open(String  fileNmae);
    //功能:打开本地磁盘上的某个文件
    //参数:文件路径
    //返回值:成功打开返回真,否则返回假
    if(!video.open(0))
    {
        QMessageBox::information(this, "提示","视频打开失败");
        return;
    }
 
 
    //启动一个定时器,用于每隔给定的时间后,在界面上展示新的图像
    cameraTimerId = this->startTimer(30);
 
 
    //将打开摄像头按钮设置成禁用
    ui->openCameraBtn->setEnabled(false);
    ui->closeCameraBtn->setEnabled(true);
 
 
}
 
 
//关闭摄像头按钮对应的槽函数
void Widget::on_closeCameraBtn_clicked()
{
    //关闭定时器
    this->killTimer(cameraTimerId);
 
 
    //关闭摄像头
    video.release();
 
 
    //清空容器内容
    ui->cameraLab->clear();
 
 
    //将按钮进行设置
    ui->closeCameraBtn->setEnabled(false);
    ui->openCameraBtn->setEnabled(true);
}
 
 
//人脸录入按钮对应的槽函数
void Widget::on_inputFaceBtn_clicked()
{
    //将关闭摄像头按钮禁用
    ui->closeCameraBtn->setEnabled(false);
 
 
    //给人脸识别器分配内容
    recognizer =  LBPHFaceRecognizer::create();
 
 
    qDebug()<<"开始录入人脸....";
    inputTimerId = this->startTimer(50);        //每隔50毫秒,调用一次事件处理函数
 
 
}
 
 
//人脸登录按钮对应的槽函数
void Widget::on_faceLoginBtn_clicked()
{
    //找到人脸模型
    QFile file("D:/opencv/resources/myface.xml");
 
 
    //装载人脸识别器对象
    if(!file.exists())
    {
        QMessageBox::information(this,"提示", "无数据可用");
        return;
    }
    recognizer = FaceRecognizer::load<LBPHFaceRecognizer>("D:/opencv/resources/myface.xml");
 
 
    //启动一个定时器
    faceLoginTimerId = startTimer(50);     //每隔50毫秒检测一次
 
 
    //将相关组件禁用
    ui->closeCameraBtn->setEnabled(false);        //禁用关闭摄像头功能
    ui->faceLoginBtn->setEnabled(false);      //设置人脸登录按钮禁用
    ui->inputFaceBtn->setEnabled(false);        //禁用人脸录入功能
 
 
    //设置可信度
    recognizer->setThreshold(80);       //如果预测结果低于90,表示匹配成功
 
}
 
 


QT中的多线程


一、多线程概述


在进行桌面应用程序开发的时候, 假设应用程序在某些情况下需要处理比较复杂的逻辑, 如果只有一个线程去处理,就会导致窗口卡顿,无法处理用户的相关操作。这种情况下就需要使用多线程,其中一个线程处理窗口事件,其他线程进行逻辑运算,多个线程各司其职,不仅可以提高用户体验还可以提升程序的执行效率。
在qt中使用了多线程,有些事项是需要额外注意的:
 

1、默认的线程在Qt中称之为窗口线程,也叫主线程,负责窗口事件处理或者窗口控件数据的更新
2、子线程负责后台的业务逻辑处理,子线程中不能对窗口对象做任何操作,这些事情需要交给窗口线程处理
3、主线程和子线程之间如果要进行数据的传递,需要使用Qt中的信号槽机制


二、QThread类的介绍


2.1    常用成员函数
 

// QThread 类常用 API
// 构造函数
QThread::QThread(QObject *parent = Q_NULLPTR);
// 判断线程中的任务是不是处理完毕了
bool QThread::isFinished() const;
// 判断子线程是不是在执行任务
bool QThread::isRunning() const;
 
// Qt中的线程可以设置优先级
// 得到当前线程的优先级
Priority QThread::priority() const;
void QThread::setPriority(Priority priority);
优先级:
    QThread::IdlePriority         --> 最低的优先级
    QThread::LowestPriority
    QThread::LowPriority
    QThread::NormalPriority
    QThread::HighPriority
    QThread::HighestPriority
    QThread::TimeCriticalPriority --> 最高的优先级
    QThread::InheritPriority      --> 子线程和其父线程的优先级相同, 默认是这个
// 退出线程, 停止底层的事件循环
// 退出线程的工作函数
void QThread::exit(int returnCode = 0);
// 调用线程退出函数之后, 线程不会马上退出因为当前任务有可能还没有完成, 调回用这个函数是
// 等待任务完成, 然后退出线程, 一般情况下会在 exit() 后边调用这个函数
bool QThread::wait(unsigned long time = ULONG_MAX);
 


 
2.2    信号与槽
 

// 和调用 exit() 效果是一样的
// 代用这个函数之后, 再调用 wait() 函数
[slot] void QThread::quit();
// 启动子线程
[slot] void QThread::start(Priority priority = InheritPriority);
// 线程退出, 可能是会马上终止线程, 一般情况下不使用这个函数
[slot] void QThread::terminate();
 
// 线程中执行的任务完成了, 发出该信号
// 任务函数中的处理逻辑执行完毕了
[signal] void QThread::finished();
// 开始工作之前发出这个信号, 一般不使用
[signal] void QThread::started();
 


2.3    静态函数
 

// 返回一个指向管理当前执行线程的QThread的指针
[static] QThread *QThread::currentThread();
// 返回可以在系统上运行的理想线程数 == 和当前电脑的 CPU 核心数相同
[static] int QThread::idealThreadCount();
// 线程休眠函数
[static] void QThread::msleep(unsigned long msecs);    // 单位: 毫秒
[static] void QThread::sleep(unsigned long secs);    // 单位: 秒
[static] void QThread::usleep(unsigned long usecs);    // 单位: 微秒
 


2.4    任务处理函数
 

// 子线程要处理什么任务, 需要写到 run() 中
[virtual protected] void QThread::run();
 
 
这个run()是一个虚函数,如果想让创建的子线程执行某个任务,需要写一个子类让其继承QThread,
并且在子类中重写父类的run()方法,函数体就是对应的任务处理流程。
另外,这个函数是一个受保护的成员函数,不能够在类的外部调用,如果想要让线程执行这个函数中的业务流程,
需要通过当前线程对象调用槽函数start()启动子线程,当子线程被启动,这个run()函数也就在线程内部被调用了
 


三、多线程的实现


3.1    实现方式一


1>    添加一个新类,继承自QThread
 

class  MyThread:QThread
{
    
};
2>    重写该类中的run方法
 

void run()
{
    
}
3>    主线程中实例化自定义线程的对象
MyThread t1 = new MyThread;
4>    调用该线程中的成员函数
t1.start();


 

 
 
 
 
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


http://www.kler.cn/news/302970.html

相关文章:

  • 【hot100-java】【接雨水】
  • NCBI-get-spesis-ref-IDs_fast.py
  • AI与艺术的碰撞:当机器开始创作,创造力何在?
  • HarmonyOS4升级到Harmonyos Next(Api 11)系列教程
  • 音视频开发之旅(93)-图像超分增强之Real-ESRGAN
  • Vue 3 组合式 API
  • C++ | Leetcode C++题解之第393题UTF-8编码验证
  • RabbitMQ SDK 支持发布、消费,连接恢复,死信队列,多种使用场景
  • db.fsyncLock() 和 db.fsyncUnlock()
  • 前后端分离项目实现SSE
  • Redis Sentinel(哨兵)详解
  • 从JVM角度看对象创建过程和内存布局
  • 基于微信小程序+Java+SSM+Vue+MySQL的宿舍管理系统
  • F1C100S/F1C200S的资料来源说明
  • 快速切换淘宝最新镜像源npm
  • js 时间戳转日期格式
  • 【STM32笔记】STM32CubeIDE介绍
  • 漫谈设计模式 [18]:策略模式
  • ISO 21434与网络安全管理系统(CSMS)的协同作用
  • Java 入门指南:Java 并发编程 —— 同步工具类 Exchanger(交换器)
  • 学生请假管理系统
  • pytest钩子函数
  • Ubuntu22.04安装nginx
  • SpringBoot项目用Aspose-Words将Word转换为PDF文件正常显示中文的正确姿势
  • RP2040 C SDK clocks时钟源配置使用
  • 【Kubernetes】K8s 的鉴权管理(二):基于属性 / 节点 / Webhook 的访问控制
  • 《PhysDiff: Physics-Guided Human Motion Diffusion Model》ICCV2023
  • Rust使用Actix-web和SeaORM库开发WebAPI通过Swagger UI查看接口文档
  • 若依框架使用MyBatis-Plus中的baseMapper的方法报错Invalid bound statement (not found):
  • 中电金信:金融级数字底座“源启”:打造新型数字基础设施 筑牢千行百业数字化转型发展基石