关于这个界面,我用到了几个控件,这些控件通过Qt是非常容易构建的,窗口的话用的是QWidget,之前说了,QWidget是Qt里面几乎大部分控件的父类,QWidget的布局我使用了简单的水平布局(QHBoxLayout),但是右边的操作区域用了垂直布局(QVBoxLayout),所以应该算是混合布局吧。

控件的话,首先是显示图像的QLabel(是的,这里我用QLabel来显示图像的),然后是四个按键:加载、开始、停止和训练。在选择图片和本地视频的时候要显示加载按键,用于加载图像或视频,所以当选择摄像机的时候这个按键时隐藏的。开始和停止按键时已知显示的,训练按键时在人脸识别的时候才会显示的。然后时下拉列表QComboBox,这里有两个,分别用于显示数据的三种来源(图片、本地视频和摄像头1)、三种功能(人脸检测、人脸标定和人脸识别)。接着就是QSpinBox和QDoubleSpinBox,这两个基本上是一样的用法,只是一个是对应整数,一个对应浮点数。然后考虑到图像可能会大于界面,这个时候又不想缩放图像,那就给显示图像的QLabel套个QScrollArea,QScrollArea控件是当内部内容大于它的尺寸时,就会自动差生滑动条,垂直的和水平的。OK,差不多啦。

按钮的使用。按钮的使用也挺简单的,在头文件声明好一个按钮指针,然后在源文件中定义。比如这样:

//头文件
QPushButton *m_pLoadBtn; //源文件
m_pStartBtn = new QPushButton(this);
m_pStartBtn->setText(QString::fromWCharArray(L"开始"));
connect(m_pStartBtn, SIGNAL(clicked(bool)), this, SLOT(detectSlot(bool)));

这里在定义的时候是传进一个父控件指针的,这样的好处是可以使用Qt的内存自动回收机制,当一个控件指定了父控件的时候,会在销毁父控件前先将子控件销毁,逐层销毁回收内存。这也是很多Qt程序中定义了控件指针后没有使用delete回收内存的原因。这里QString::fromWCharArray(L"开始")这样写的原因是为了显示中文,如果不考虑显示中文的话,就直接"start"即可。connect()函数是连接了信号与槽,信号与槽的参数一般是要一致,如果不同一般就不起作用。

QComboBox的使用。

//头文件
QComboBox *m_pTypeCBox; //源文件
m_pTypeCBox = new QComboBox(this);
m_pTypeCBox->addItem(QString::fromWCharArray(L"人脸检测"), 0);
m_pTypeCBox->addItem(QString::fromWCharArray(L"人脸标定"), 1);
m_pTypeCBox->addItem(QString::fromWCharArray(L"人脸识别"), 2);
connect(m_pTypeCBox, SIGNAL(currentIndexChanged(int)), this, SLOT(typeSlot(int)));

QComboBox是下拉列表,定义的时候可以通过addItem()来添加下拉菜单里面的项目,然后可以根据currentIndex或者currentData来访问当前选中的序号或者内容。

QSpinBox和QDoubleSpinBox也是类似的用法,但是QDoubleSpinBox因为是浮点数,所以会有一个精度设置,默认是小数点后两位,但是可以通过setDecimals(n)来设置小数点后n位,因为QDoubleSpinBox的变量类型是double,所以其精度是可以设置得很高得。

QScrollArea的使用也很简单,定义好显示图片的QLabel后,通过QScrollArea的setWidget()函数,将QLabel嵌套到QScrollArea中,当QLabel的大小大于QScrollArea的时候,QScrollArea就会自动产生垂直或者水平滑动条。

然后是布局。水平布局或者垂直布局的用法都是类似的,首先是定义,然后通过addLayout()函数添加子布局或者通过addWidget添加子控件:

m_pMainHLayout = new QHBoxLayout(this);
m_pMainHLayout->addWidget(m_pFrameSArea, 10);
m_pMainHLayout->addLayout(m_pChildVLayout, 1);

后面的数字是设置子控件或者子布局在布局中的比例,Qt并不会严格执行,只是适当调整满足要求。布局设置好之后,要将布局放到QWidget中,通过QWidget的setLayout()函数实现。这里需要注意的是,父布局的定义要先于子布局,不然会出现问题的,比如这样是不行的:

m_pChildVLayout = new QVBoxLayout(this);
m_pMainHLayout = new QHBoxLayout(this);
m_pMainHLayout->addLayout(m_pChildVLayout, 1);

但是,调整为这样就可以:

m_pMainHLayout = new QHBoxLayout(this);
m_pChildVLayout = new QVBoxLayout(this);
m_pMainHLayout->addLayout(m_pChildVLayout, 1);

好了,界面部分大致就是这样,其实我感觉没啥好说的,我写的界面一般就仅限于能展示就行了。

比较完整的代码:

头文件部分:

class QScrollArea;
class QLabel;
class QComboBox;
class QSpinBox;
class QDoubleSpinBox;
class QPushButton;
class QHBoxLayout;
class QVBoxLayout;
class QTimer;
class QTextEdit; //Qt控件
QScrollArea *m_pFrameSArea;
QLabel *m_pFrameQLab;
QLabel *m_pMinFaceSzQLabel;
QSpinBox *m_pMinFaceSzQSBox;
QLabel *m_pScoreThresholdQLabel;
QDoubleSpinBox *m_pScoreThresholdQSBox;
QLabel *m_pImgPyramidScaleQLabel;
QDoubleSpinBox *m_pImgPyramidScaleQSBox;
QLabel *m_pWinStepQLabel;
QSpinBox *m_pWinStepQSBox;
QComboBox *m_pCameraCBox;
QComboBox *m_pTypeCBox;
QLabel *m_pRecognizerScoreQLabel;
QDoubleSpinBox *m_pRecognizerScoreQSBox;
QPushButton *m_pLoadBtn;
QPushButton *m_pStartBtn;
QPushButton *m_pStopBtn;
QPushButton *m_pTrainBtn;
QTextEdit *m_pTextEdit; //Qt布局
QHBoxLayout *m_pMainHLayout;
QVBoxLayout *m_pChildVLayout;
QHBoxLayout *m_pMinFaceSzHLayout;
QHBoxLayout *m_pScoreThresholdHLayout;
QHBoxLayout *m_pImgPyramidScaleHLayout;
QHBoxLayout *m_pWinStepHLayout;
QHBoxLayout *m_pRecognizerScoreHLayout;

源文件部分:

QFont font;
font.setPixelSize(18);
this->setFont(font); m_pFrameSArea = new QScrollArea(this);
m_pFrameSArea->setAlignment(Qt::AlignCenter); m_pFrameQLab = new QLabel(m_pFrameSArea);
m_pFrameQLab->setAlignment(Qt::AlignCenter);
m_pFrameSArea->setWidget(m_pFrameQLab); m_pMinFaceSzQLabel = new QLabel(this);
m_pMinFaceSzQLabel->setText(QString::fromLocal8Bit("最小尺寸"));
m_pMinFaceSzQSBox = new QSpinBox(this);
m_pMinFaceSzQSBox->setMinimum(4);
m_pMinFaceSzQSBox->setMaximum(512);
m_pMinFaceSzQSBox->setSingleStep(1);
m_pMinFaceSzQSBox->setValue(40);
connect(m_pMinFaceSzQSBox, SIGNAL(valueChanged(int)), 
    m_pSeetaFaceThread, SLOT(setMinFaceSizeSlot(int))); m_pScoreThresholdQLabel = new QLabel(this);
m_pScoreThresholdQLabel->setText(QString::fromLocal8Bit("检测阈值"));
m_pScoreThresholdQLabel->hide();
m_pScoreThresholdQSBox = new QDoubleSpinBox(this);
m_pScoreThresholdQSBox->setMaximum(1.0);
m_pScoreThresholdQSBox->setMinimum(0.001);
m_pScoreThresholdQSBox->setSingleStep(0.001);
m_pScoreThresholdQSBox->setDecimals(3);
m_pScoreThresholdQSBox->setValue(0.5);
m_pScoreThresholdQSBox->hide();
connect(m_pScoreThresholdQSBox, SIGNAL(valueChanged(double)), 
    m_pSeetaFaceThread, SLOT(setScoreThreshSlot(double))); m_pImgPyramidScaleQLabel = new QLabel(this);
m_pImgPyramidScaleQLabel->setText(QString::fromLocal8Bit("缩放尺度"));
m_pImgPyramidScaleQSBox = new QDoubleSpinBox(this);
m_pImgPyramidScaleQSBox->setMaximum(1.0);
m_pImgPyramidScaleQSBox->setMinimum(0.0);
m_pImgPyramidScaleQSBox->setSingleStep(0.1);
m_pImgPyramidScaleQSBox->setDecimals(1);
m_pImgPyramidScaleQSBox->setValue(0.8);
connect(m_pImgPyramidScaleQSBox, SIGNAL(valueChanged(double)), 
    m_pSeetaFaceThread, SLOT(setmagePyramidScaleFactorSlot(double))); m_pWinStepQLabel = new QLabel(this);
m_pWinStepQLabel->setText(QString::fromLocal8Bit("窗口步长"));
m_pWinStepQSBox = new QSpinBox(this);
m_pWinStepQSBox->setMinimum(2);
m_pWinStepQSBox->setMaximum(64);
m_pWinStepQSBox->setSingleStep(1);
m_pWinStepQSBox->setValue(4);
connect(m_pWinStepQSBox, SIGNAL(valueChanged(int)), 
    m_pSeetaFaceThread, SLOT(setWindowStepSlot(int))); m_pCameraCBox = new QComboBox(this);
connect(m_pCameraCBox, SIGNAL(currentIndexChanged(int)), this, 
    SLOT(cameraSlot(int)));
m_pLoadBtn = new QPushButton(this);
m_pLoadBtn->setText(QString::fromWCharArray(L"加载"));
connect(m_pLoadBtn, SIGNAL(clicked(bool)), this, 
    SLOT(loadSlot(bool))); m_pTypeCBox = new QComboBox(this);
m_pTypeCBox->addItem(QString::fromWCharArray(L"人脸检测"), 0);
m_pTypeCBox->addItem(QString::fromWCharArray(L"人脸标定"), 1);
m_pTypeCBox->addItem(QString::fromWCharArray(L"人脸识别"), 2);
connect(m_pTypeCBox, SIGNAL(currentIndexChanged(int)), this, 
    SLOT(typeSlot(int))); m_pRecognizerScoreQLabel = new QLabel(this);
m_pRecognizerScoreQLabel->setText(QString::fromLocal8Bit("识别阈值"));
m_pRecognizerScoreQSBox = new QDoubleSpinBox(this);
m_pRecognizerScoreQSBox->setMinimum(0.0);
m_pRecognizerScoreQSBox->setMaximum(100);
m_pRecognizerScoreQSBox->setSingleStep(0.1);
m_pRecognizerScoreQSBox->setDecimals(2);
m_pRecognizerScoreQSBox->setValue(50.0);
connect(m_pRecognizerScoreQSBox, SIGNAL(valueChanged(double)), 
    m_pSeetaFaceThread, SLOT(setRecognizerScoreSlot(double))); m_pStartBtn = new QPushButton(this);
m_pStartBtn->setText(QString::fromWCharArray(L"开始"));
connect(m_pStartBtn, SIGNAL(clicked(bool)), this, 
    SLOT(detectSlot(bool))); m_pStopBtn = new QPushButton(this);
m_pStopBtn->setText(QString::fromWCharArray(L"停止"));
m_pStopBtn->setEnabled(false);
connect(m_pStopBtn, SIGNAL(clicked(bool)), this, 
    SLOT(stopSlot(bool))); m_pTrainBtn = new QPushButton(this);
m_pTrainBtn->setText(QString::fromWCharArray(L"训练"));
m_pTrainBtn->hide();
connect(m_pTrainBtn, SIGNAL(clicked(bool)), this, 
    SLOT(trainSlot(bool))); m_pTextEdit = new QTextEdit(this); m_pMainHLayout = new QHBoxLayout(this);
m_pChildVLayout = new QVBoxLayout(this); m_pMinFaceSzHLayout = new QHBoxLayout(this);
m_pMinFaceSzHLayout->addWidget(m_pMinFaceSzQLabel);
m_pMinFaceSzHLayout->addWidget(m_pMinFaceSzQSBox);
m_pScoreThresholdHLayout = new QHBoxLayout(this);
m_pScoreThresholdHLayout->addWidget(m_pScoreThresholdQLabel);
m_pScoreThresholdHLayout->addWidget(m_pScoreThresholdQSBox);
m_pImgPyramidScaleHLayout = new QHBoxLayout(this);
m_pImgPyramidScaleHLayout->addWidget(m_pImgPyramidScaleQLabel);
m_pImgPyramidScaleHLayout->addWidget(m_pImgPyramidScaleQSBox);
m_pWinStepHLayout = new QHBoxLayout(this);
m_pWinStepHLayout->addWidget(m_pWinStepQLabel);
m_pWinStepHLayout->addWidget(m_pWinStepQSBox);
m_pRecognizerScoreHLayout = new QHBoxLayout(this);
m_pRecognizerScoreHLayout->addWidget(m_pRecognizerScoreQLabel);
m_pRecognizerScoreHLayout->addWidget(m_pRecognizerScoreQSBox); m_pChildVLayout->setAlignment(Qt::AlignTop);
m_pChildVLayout->addWidget(m_pCameraCBox);
m_pChildVLayout->addWidget(m_pLoadBtn);
m_pChildVLayout->addWidget(m_pTypeCBox);
m_pChildVLayout->addLayout(m_pMinFaceSzHLayout);
m_pChildVLayout->addLayout(m_pScoreThresholdHLayout);
m_pChildVLayout->addLayout(m_pImgPyramidScaleHLayout);
m_pChildVLayout->addLayout(m_pWinStepHLayout);
m_pChildVLayout->addLayout(m_pRecognizerScoreHLayout);
m_pChildVLayout->addWidget(m_pStartBtn);
m_pChildVLayout->addWidget(m_pStopBtn);
m_pChildVLayout->addWidget(m_pTrainBtn);
m_pChildVLayout->addWidget(m_pTextEdit); m_pMainHLayout->addWidget(m_pFrameSArea, 10);
m_pMainHLayout->addLayout(m_pChildVLayout, 1); this->setLayout(m_pMainHLayout);

OK,界面部分大致就是这样。

桃红复含宿雨,柳绿更带朝烟。

花落家童未扫,莺啼山客犹眠。

  --王维 《田园乐七首·其六 / 闲居》

SeetaFaceQt:写一个简单的界面的更多相关文章

  1. Java写一个简单学生管理系统

    其实作为一名Java的程序猿,无论你是初学也好,大神也罢,学生管理系统一直都是一个非常好的例子,初学者主要是用数组.List等等来写出一个简易的学生管理系统,二.牛逼一点的大神则用数据库+swing来 ...

  2. 用java写一个用户登陆界面

    一.课堂测试源代码及其结果截图 用java的swing写一个用户登录界面,采用网格布局.源代码如下: /** * */package LiuLijia; import java.awt.CardLay ...

  3. django写一个简单的登陆注册

    要写这个,前提还是需要知道三个知识: 一个是urls.py,它是写我们的路由关系的,之前我写了通过wsgiref写一个简单的服务端,也用到了路由,就是 请求过来的url和视图函数的对应关系. 二是就是 ...

  4. 用C写一个简单的推箱子游戏(一)

    我现在在读大二,我们有一门课程叫<操作系统>,课程考查要求我们可以写一段程序或者写Windows.iOS.Mac的发展历程.后面我结合网上的资料参考,就想用自己之前简单学过的C写一关的推箱 ...

  5. 用Python写一个简单的Web框架

    一.概述 二.从demo_app开始 三.WSGI中的application 四.区分URL 五.重构 1.正则匹配URL 2.DRY 3.抽象出框架 六.参考 一.概述 在Python中,WSGI( ...

  6. 如何写一个简单的http服务器

    最近几天用C++写了一个简单的HTTP服务器,作为学习网络编程和Linux环境编程的练手项目,这篇文章记录我在写一个HTTP服务器过程中遇到的问题和学习到的知识. 服务器的源代码放在Github. H ...

  7. 如何写一个简单的shell

    如何写一个简单的shell 看完<UNIX环境高级编程>后我就一直想写一个简单的shell来作为练习,因为有事断断续续的写了好几个月,如今写了差不多来总结一下. 源代码放在了Github: ...

  8. 分享:计算机图形学期末作业!!利用WebGL的第三方库three.js写一个简单的网页版“我的世界小游戏”

    这几天一直在忙着期末考试,所以一直没有更新我的博客,今天刚把我的期末作业完成了,心情澎湃,所以晚上不管怎么样,我也要写一篇博客纪念一下我上课都没有听,还是通过强大的度娘完成了我的作业的经历.(当然作业 ...

  9. 一步一步写一个简单通用的makefile(三)

    上一篇一步一步写一个简单通用的makefile(二) 里面的makefile 实现对通用的代码进行编译,这一章我将会对上一次的makefile 进行进一步的优化. 优化后的makefile: #Hel ...

随机推荐

  1. 记一次Redis+Getshell经验分享

    前言: 当我们接到一个授权渗透测试的时候,常规漏洞如注入.文件上传等尝试无果后,扫描端口可能会发现意外收获. 知己知彼乃百战不殆,Redis介绍: 简单来说 redis 就是一个Key-Value类型 ...

  2. 065、Java面向对象之定义一个Book类,在主类中使用Book类

    01.代码如下: package TIANPAN; class Book { // 定义一个新的类 String title; // 书的名字 double price; // 书的价格 public ...

  3. 5 GC 参数

  4. NirSoft 实用程序

    64-bit (x64) utilities package 此软件包包含NirSoft中的所有实用程序,这些实用程序具有64位版本(x64)Windows的独立构建. 此程序包包含下面列表中每个实用 ...

  5. Tips for traing DNN

    1.   一般的机器学习方法不会在train好的模型上检查training data的结果,因为DNN在training data上都没有办法获得很好的正确率, 所以要先回头看一下要对模型做什么修改, ...

  6. scala文件通过本地命令运行

    1.准备(检查) a.本地环境安装jdk b.安装scala 2.sublime编辑scala文件,并存放到F:\plan_next\scala_compile下 3.文件目录中切换到cmd中(文件目 ...

  7. springboot启动总是启动不起来UnsatisfiedDependencyException异常

    采用debug模式启动总是停留在 点击后: 鼠标放在ex上: org.springframework.beans.factory.UnsatisfiedDependencyException: Err ...

  8. 永久免费云服务器搭建国内Moon服务加速ZeroTier

    ZeroTier One本身的服务器都在国外访问速度很慢.可以通过搭建国内Moon服务加速解决连接慢的问题. 但是需要有固定外网IP的服务器,可以注册sanfengyun账号申请免费云服务器. 下面是 ...

  9. vue学习(八)nextTick[异步更新队列]的使用和应用

    nextTick的使用 为了数据变化之后等待vue完成更新DOM,可以在数据变化之后立即使用Vue.nextTick()在当前的回调函数中能获取最新的DOM <div id="app& ...

  10. EE将于5月30日在英国推出首个5G网络

    英国移动运营商 EE 宣布计划于周三在英国推出 5G,该网络将于 5 月 30 日开通,第一批 5G 手机可从今天开始预订.EE 最初的 5G 网络部署将集中在六个城市(伦敦,加的夫,爱丁堡,贝尔法斯 ...