勇哥的VC++应用框架学习之QT(1) 信号槽、按钮控件、opencv读取显示图片

前言

勇哥对于C语言,C++早些年有一些接触,这个系列贴子就记载一下C++应用框架的学习经验。
在写程序时,UI、基础类库、应用程序框架对于vc来讲,只能依靠MFC和QT了。
勇哥对MFC有很强的抵触,它长得丑,很多地方反人类,唯一的好处是VC原生自带的。
所以还是先研究一下QT,再研究MFC吧,否则会带了很大的挫折感。
另外,采用vc++进行.net开发,即托管方式开发,可以使用WPF做界面,在有些公司也是被采用的方案,
这方面勇哥是全盲,也要抓紧研究一下。
所有将要做的这一切,都是想为OpenCV服务!
加油。。。


第一篇笔记开始研究QT,包含下面的内容:


1、创建第一个Qt程序

2、熟悉按钮控件常用API

3、对象树的基本概念

4、Qt中的坐标系统

5、信号和槽的基本使用以及拓展

6、opencv读取显示图片



QT的模块,我们后续先研究点有用的,包括:Qt Widgets, Qt Core, Qt GUI, Qt Network。

下图是QTv5版的模块。如果是v5版以下,Qt Widgets是被包含在GUI中的。

image.png

先把练习程序放上来。

它的工程是这样的:

image.png

很简单,图片是opencv读入,并用QT控件显示的。

几个按钮是代码创建的,重点是熟悉信号槽的用法,它的作用就是用来完成类似C#中的按钮的事件。


image.png

先提供源代码。


MyButton.h

#pragma once

#include <QWidget>
#include <qpushbutton.h>

class MyButton : public QPushButton
{
	Q_OBJECT

public:
	MyButton(QWidget *parent);
	~MyButton();
};

QtForOpencv.h

#pragma once
#pragma execution_character_set("utf-8")

#include <QtWidgets/QWidget>
#include "ui_QtForOpencv.h"
#include <QLabel>
#include "student.h"
#include "teacher.h"


class QtForOpencv : public QWidget
{
	Q_OBJECT

public:
	QtForOpencv(QWidget *parent = Q_NULLPTR);
	~QtForOpencv();
    void clickfun();
	void classIsOver();  //下课了(无参数)
	void classIsOver2(QString name);  //下课了(有参数)
	void btn1Fun();

private:
	Ui::QtForOpencvClass ui;
public:
	QLabel* imgLabel;
	Teacher* tc;
	Student* st;


};

student.h

#pragma once
#pragma execution_character_set("utf-8")

#include <QObject>

class Student : public QObject
{
	Q_OBJECT

public:
	Student(QObject *parent);
	~Student();

public slots:
	//低版本写在这里,高版本直接写到public下面。
	//槽函数返回void,它需要声明也需要实现。
	//槽函数可以有参数,可以发生重载
	void eat();
	void eat(QString name);   //有参数的槽函数
};

teacher.h

#pragma once

#include <QObject>

class Teacher : public QObject
{
	Q_OBJECT

public:
	Teacher(QObject *parent);
	~Teacher();
signals:
	//信号必须void,可以有参数。
	//信号只需要声明,不需要实现。
	void hugry();
	void hugry(QString name);
};


main.cpp

#include "QtForOpencv.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	QtForOpencv w;
	w.show();
	return a.exec();
}

MyButton.cpp

#include "MyButton.h"
#include <QDebug.h>
MyButton::MyButton(QWidget *parent)
	: QPushButton(parent)
{

}

MyButton::~MyButton()
{
	qDebug() << QStringLiteral("MyButton的析构");
}

QtForOpencv.cpp

#include "QtForOpencv.h"
#include <opencv2\opencv.hpp>
#include <opencv2\core.hpp>
#include <opencv2\imgcodecs.hpp>
#include <opencv2\imgproc.hpp>
#include <qpushbutton.h>
#include "MyButton.h"
#include <QDebug.h>
#include <qmessagebox.h>

using namespace cv;
using namespace std;
QtForOpencv::QtForOpencv(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);

	QPushButton* btn = new QPushButton();
	
	btn->setParent(this);
	btn->setText(QStringLiteral("push按钮1"));
	//按下后执行btn1Fun,弹出一个messagebox
	connect(btn, &QPushButton::clicked, this, &QtForOpencv::btn1Fun);
	
	QPushButton* btn2 = new QPushButton(QStringLiteral("push按钮2"), this);
	resize(600, 400);
	btn2->move(100, 100);
	btn2->resize(150, 50);
	//按下后直接关闭当前窗口
	connect(btn2, &MyButton::clicked, this, &QtForOpencv::close);
	
	
	setWindowTitle(QStringLiteral("这是父窗口的标题"));
	setFixedSize(600, 600);

	MyButton* btn3 = new MyButton(this);
	btn3->setText(QStringLiteral("自定义按钮"));
	btn3->move(100, 200);

	//信号发送者,发送的信号,信号的接收者,处理的槽函数
	//按下后输出一句话在调试窗口
	connect(btn3, &MyButton::clicked, this, &QtForOpencv::clickfun);

	//自动定义信号和槽函数
	//两个类 Teacher,Student类
	//下课后, 老师tc发一个信号  “饿了”
	//学生st响应这个信号,处理槽函数  “请客吃饭 ”
	tc = new Teacher(this);
	st = new Student(this);
	
	//下面是信号与槽函数没有参数没有重载情况下的写法
	//connect(tc, &Teacher::hugry, st, &Student::eat);
	//classIsOver();

	//下面是信号与槽函数都有重载的情况下的写法
	void(Teacher:: *tSignal)(QString) = &Teacher::hugry;
	void(Student:: *sSignal)(QString) = &Student::eat;
	connect(tc, tSignal, st, sSignal);
	classIsOver2("东莞烧鸭");
	
	//演示opencv载入图片并显示
	Mat src = imread("e:/1.jpg");  // 读取图片
	if (src.empty()) {
		printf("could not load image...\n");
	}
	cvtColor(src, src, COLOR_BGR2RGB); //BGR图片装换成RGB图片
	cv::resize(src, src, Size(300, 300));  // 修改图片大小

	imgLabel = new QLabel(this);
	imgLabel->setText(QStringLiteral("原图"));
	imgLabel->move(200, 200);
	QImage showImg = QImage((const unsigned char*)(src.data), src.rows, src.cols, QImage::Format_RGB888);
	imgLabel->setPixmap(QPixmap::fromImage(showImg));

	imgLabel->show();  // 在qt界面显示图片 

	waitKey(0);

}

void QtForOpencv::btn1Fun()
{
	//演示了QMessageBox的用法
	qDebug() << QStringLiteral("按了btn1按钮");
	QMessageBox::StandardButton rb = QMessageBox::information(NULL, "Title", "按钮一被按下了!", 
		QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
	if (rb == QMessageBox::Yes)
	{
		QMessageBox::aboutQt(NULL, "About Qt");
	}

}

void QtForOpencv::clickfun()
{
	qDebug() << QStringLiteral("按了btn3按钮");
}

QtForOpencv::~QtForOpencv()
{
	qDebug() << QStringLiteral("QtForOpencv析构");
}

void QtForOpencv::classIsOver()
{
	//触发老师饿了的信号
	//这个信号是自定义信号,触发自定义的信号关键字是emit
	emit tc->hugry();
}

void QtForOpencv::classIsOver2(QString name)
{
	//触发老师饿了的信号
	//这个信号是自定义信号,触发自定义的信号关键字是emit
	emit tc->hugry("东莞烧鸭");
}

student.cpp

#include "student.h"
#include <Qdebug.h>
Student::Student(QObject *parent)
	: QObject(parent)
{
}

Student::~Student()
{
}

void Student::eat()
{
	qDebug() << QStringLiteral("学生收到了,准备请老师吃饭");
}

void Student::eat(QString name)
{
	//注意下面两句的区别
	//直接引号的字符串是char*, 第二句是把QString转为char*
	//qDebug() << QStringLiteral("学生收到了,准备请老师吃饭: ") << name;
	qDebug() << "学生收到了,准备请老师吃饭: " << name.toUtf8().data();
}

teacher.cpp

#include "teacher.h"

Teacher::Teacher(QObject *parent)
	: QObject(parent)
{
}

Teacher::~Teacher()
{
}


代码里的一些知识点:

Main函数

QApplication a  应用程序对象  有且仅有一个

a.exec() 进行消息循环  阻塞

MyWidget w  窗口对象

默认不会弹出窗口 想要显示窗口 需要调用 show

QPushButton

QPushButton * btn  = new QPushButton;

btn->setParent(this) 设置父亲

btn->setText (“aaa”)

btn->move( x, y)

重置窗口大小  resize(w,h)

重置窗口标题  setWindowTitle(“aaaa”)

设置固定窗口大小  setFixedSize(w,h)

对象树

所有new出来的对象 不用管释放

原因 children表中的对象会在窗口关闭后进行自动释放

Qt中的坐标系

x正向 →

y正向 ↓

Qt中的信号和槽

需求 点击按钮 关闭窗口

connect(  信号发送者,发送的信号,信号接受者,处理槽函数 )

优点  松散耦合

Qt中的自定义信号和槽

自定义信号

返回值 void

需要声明 不需要实现

可以有参数

自定义槽函数

返回值void

需要声明 需要实现

可以有参数

触发自定义的信号

emit

当自定义信号和槽 出现重载时候,原先写法失效,因为执行的函数地址不明确

解决方法: 利用函数指针 来明确指向哪个函数的地址

QString转char*    toUtf8 转 QBtyeArray 类型  在利用data 转成char*

信号和槽的拓展

信号是可以连接信号的

信号和槽可以断开  disconnect

一个信号可以连接多个槽函数

多个信号可以连接同一个槽函数

信号和槽函数的个数必须一一对应

信号的参数个数 可以大于槽函数的参数个数 ,反之不可以


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2025年4月    »
123456
78910111213
14151617181920
21222324252627
282930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864