1. 第一天课程安排
1、Qt的介绍
2、Qt的框架
3、项目文件(.pro)
4、第一个Qt程序
5、父窗口和子窗口的区别(空间,部件,构件)
6、信号和槽
7、坐标系统
8、内存回收机制 new delete
9、带菜单栏的窗口
10、对话框
2. 第二天课程安排
1、界面设置器的使用
2、常用控件
3、布局
4、自定义控件
5、常用事件的处理
3. 第三天课程安排
1、Qpainter绘图
2、绘图设备(Qpixmap,QImage,QBitmap,QPicture)
3、文件操作(QFile,QFileInfo,QDataStream二进制流,QTextStream,QBuffter)
4.第四天课程安排
1、TCP编程
2、UDP编程
3、UDP传输图片
4、多线程编程(多任务)
5.第五天课程安排
1、数据库编程
2、汽车销售管理系统
第一天
1、Qt概述
Qt是一个**跨平台**的C++**图形用户界面应用程序框架**(GUI编程)
2、编写程序
运行:ctrl+r
.h和对应的.cpp文件相互切换:F4
Qt项目文件的注释:#
Qt的帮助文档:F1
快速注释/取消:ctrl+/
项目的移植:要删除项目文件夹里的.USER文件,并且打开项目,点击项目按钮更改里面的路径
1)main.cpp:
1 #include "mywidget.h" 2 3 //QApplication应用程序类 4 //Qt头文件没有.h 5 //头文件和类名一样,一般以Q开头,头两个字母大写 6 #include <QApplication> 7 8 int main(int argc, char *argv[]) 9 { 10 //有且只有一个应用程序类的对象 11 QApplication a(argc, argv); 12 13 //MyWidget继承于QWidge,QWidge是一个窗口基类 14 //所以Mywidge也是一个窗口类 15 //w就是一个窗口(对象) 16 MyWidget w; 17 18 //窗口创建默认是隐藏的,需要人为显示 19 w.show(); 20 21 // return a.exec();等价于下面两句 22 //让程序一直执行,等待用户操作 23 //等待事件的发生 24 a.exec(); 25 26 return 0; 27 }
2)main函数的基本框架
1 #include<QApplication> 2 int main(int argc,char *argv[]) 3 { 4 QApplication a(argc,argv); 5 //我们写的代码 6 return a.exec(); 7 }
3)Qt5的基本模块
4)helloQt
1 #include<QApplication> 2 #include<QWidget>//创建一个窗口 3 #include<QPushButton> 4 5 int main(int argc,char *argv[]) 6 { 7 QApplication a(argc,argv); 8 9 QWidget w; 10 w.setWindowTitle("啊哈哈哈");//设置标题 11 12 13 QPushButton b; 14 b.setText("^_^");//给按钮设置内容 15 // b.show(); 16 b.setParent(&w);//指定父对象 17 b.move(100,100);//移动坐标,以左上角为原点 18 19 /*如果不指定父对象,对象和对象(窗口和窗口)没有关系,相互独立 20 * a指定b为他的父对象,a放在b的上面 21 * 指定父对象有2种方式: 22 * 1)setParent 23 * 2)通过构造函数传参 24 * 指定父对象,只需要父对象显示,上面的子对象自动显示 25 * 父对象-子对象,父窗口-子窗口,父控件-子控件 26 */ 27 28 29 QPushButton b1(&w);//通过构造函数传参 30 b1.setText("lalal"); 31 32 33 w.show(); 34 35 a.exec(); 36 return 0; 37 }
6)信号和槽:Qt对象之间通信的接口
按钮只是产生一个软件中断,调用槽函数,而按完按钮后产生的事件(如关程序、发信号等)由槽函数所有者完成,与按钮无关
7)函数指针
void fun(int)
{
}
void (*p)(int)=fun;
8)连接函数(连接信号与槽函数):connect
connect(&b1,&QPushButton::pressed,this,&MainWidget::close);
* &b1:信号发出者,指针类型
* &QPushButton::pressed:触发的信号, &发出者的类名::信号的名字
* this:信号接收者
* &MainWidget::close:处理的槽函数,信号处理函数 &接收者的类名::槽函数名字
9)自定义槽函数:
*Qt5:任意成员函数,普通全局函数,静态函数,lambda表达式
*槽函数需要和信号一致(参数,返回值)
*由于信号都是没有返回值的,所以槽信号一定没有返回值
*信号和槽的参数个数可以不一样
信号的参数个数可以大于槽函数的参数个数
槽信号的参数个数不可以大于信号参数个数
例:connect(b2,&QPushButton::released,this,&MainWidget::MySlot);
void MainWidget::MySlot()
{
b2->setText("123");
}
10)信号重载的处理方式
1 signals: 2 /*信号必须有signals关键字 3 * 信号没有返回值,但可以有参数 4 * 信号就是函数的声明,只需声明,无需定义 5 * 使用:emit mySignal() 6 * 信号可以重载 7 */ 8 void mySignal(); 9 void mySignal(int,QString);//QString是Qt的字符串表现形式,信号有两个参数,槽函数也要有两个参数且一一对应。信号是给槽函数传参
调用:
//connect(&subWin,&SubWidget::mySignal,this,&MainWidget::dealSub);//没法判断是接收哪个信号
//connect(&subWin,&SubWidget::mySignal,this,&MainWidget::dealSlot);//没法判断是接收哪个信号
解决:
* 方法一:函数指针
void (subWidget::*funSignal)()=&subWidget::mySignal;
connect(&w,funSignal,this,&MainWidget::dealSub);//不带参
void (subWidget::*testSignal)(int,QString)=&subWidget::mySignal;
connect(&w,testSignal,this,&MainWidget::dealSlot);//带参
* 方法二:Qt4的信号连接
connect(&w,SIGNAL(mySignal()),this,SLOT(dealSub()));
connect(&w,SIGNAL(mySignal(int,QString)),this,SLOT(dealSlot(int,QString)));
不推荐Qt4,原因:
1)SIGNAL SLOT 在编译时将函数名字 -> 字符串 不进行错误检查(运行时才报)
2)Qt4槽函数必须有slots关键字来修饰
public slots:
void dealSub();
void dealSlot(int,QString);
* 方法三:Lambda表达式,匿名函数对象:
C++11增加的新特性 ,项目文件添加 :CONFIG += C++11
Qt配合信号使用会非常方便
1 QPushButton *b4=new QPushButton(this); 2 b4->setText("Lambda表达式"); 3 b4->move(150,150); 4 int a=10,b=100; 5 connect(b4,&QPushButton::released, 6 // [b4,a,b]() 7 //=:把外部所有局部变量、类中所有成员以值传递方式传进来 8 //this:类中所有成员以值传递方式传进来 9 //&:把外部所有局部变量以引用方式传进来 10 //[&]()//不建议使用引用方式,可能访问非法内存(生命周期) 11 [=]() mutable//若在其后加上mutable关键字,则表示允许更改 12 { 13 b4->setText("123"); 14 qDebug()<<"11111";//qDebug(),调试打印函数 15 qDebug()<<a<<b; 16 //a=11;//值传递,变量为只读(不加mutable) 17 a=11;//加了mutable允许更改 18 } 19 //connect(b4,&QPushButton::clicked,//信号带参数 20 //[=](bool isCheck) 21 //{ 22 // qDebug()<<isCheck;//clicked的默认参数false传参给isCheck 23 //} 24 );
注:详见day01/工程 03_SignalAndSlot
11)坐标系统:
窗口、控件的位置移动都是move()函数
①对于父窗口(主窗口),坐标系统相对于屏幕
原点:相对于屏幕左上角
x:往右递增
y:往下递增
②对于子窗口,坐标系统相对于父窗口
原点:相对于窗口空白区域左上角(不包括边框)
x:往右递增
y:往下递增
12)内存回收机制
①指定父对象后 ②直接或间接继承QObject(对象树)
子对象如果是动态分配空间new,不需要手动释放delete
系统会手动释放
13)带菜单栏的窗口QMainWindow
1 #include<QMenuBar>//菜单栏头文件 2 #include<QMenu>//菜单 3 #include<QAction>//菜单项 4 #include<QDebug> 5 #include<QToolBar>//工具栏 6 #include<QPushButton> 7 #include<QStatusBar>//状态栏 8 #include<QLabel>//标签 9 #include<QTextEdit>//文本编辑 10 #include<QDockWidget>//浮动窗口 11 12 MainWindow::MainWindow(QWidget *parent) 13 : QMainWindow(parent) 14 { 15 //菜单栏 16 QMenuBar *mBar=menuBar(); 17 //添加菜单 18 QMenu *pFile=mBar->addMenu("文件"); 19 //添加菜单项,添加动作 20 QAction *pNew=pFile->addAction("新建"); 21 connect(pNew,&QAction::triggered, 22 []() 23 { 24 qDebug()<<"新建被按下"; 25 } 26 ); 27 *pFile->addSeparator();//添加分割线 28 QAction *pOpen=pFile->addAction("打开"); 29 30 31 32 //工具栏,菜单项的快捷方式 33 QToolBar *toolBar=addToolBar("toolBar"); 34 //工具栏添加快捷键 35 toolBar->addAction(pNew); 36 37 QPushButton *b=new QPushButton(this); 38 b->setText("^_^"); 39 //添加小控件 40 toolBar->addWidget(b); 41 connect(b,&QPushButton::clicked, 42 [=]() 43 { 44 b->setText("#_#"); 45 } 46 ); 47 48 49 //状态栏 50 QStatusBar *sBar=statusBar(); 51 //标签 52 QLabel *label=new QLabel(this); 53 label->setText("Normal text file"); 54 sBar->addWidget(label); 55 //addWidget 从左往右添加 56 sBar->addWidget(new QLabel("2",this)); 57 58 //addPermanentWidget 从右往左添加 59 sBar->addPermanentWidget(new QLabel("1",this)); 60 61 62 63 //核心控件,如文本编辑区 64 QTextEdit *textEdict=new QTextEdit(this); 65 setCentralWidget(textEdict);//将其设置为核心控件 66 67 68 //浮动窗口 69 QDockWidget *dockWidget=new QDockWidget(this); 70 addDockWidget(Qt::RightDockWidgetArea,dockWidget); 71 //在浮动窗口添加控件(文本编辑区) 72 QTextEdit *t=new QTextEdit(this); 73 dockWidget->setWidget(t); 74 75 }
14)对话框
1 #include<QMenuBar> 2 #include<QMenu> 3 #include<QAction> 4 #include<QDialog> 5 #include<QMessageBox>//标准对话框 6 #include<QFileDialog>//文件对话框 7 QMenuBar *mBar=menuBar(); 8 setMenuBar(mBar); 9 QMenu *menu=mBar->addMenu("对话框"); 10 QAction *p1=menu->addAction("模态对话框"); 11 connect(p1,&QAction::triggered, 12 [=]() 13 { 14 QDialog dlg; 15 dlg.exec(); 16 qDebug()<<"1111"; 17 } 18 ); 19 QAction *p2=menu->addAction("非模态对话框"); 20 connect(p2,&QAction::triggered, 21 [=]() 22 { 23 // //QDialog dlg;//局部变量,对话框闪一下就没了,换成成员或动态分配 24 // dlg.show(); 25 // qDebug()<<"222"; 26 27 // QDialog *dlg=new QDialog;//若多次点击会多次分配内存,内存浪费 28 // dlg->show(); 29 30 //不指定父对象 31 QDialog *p=new QDialog; 32 p->setAttribute(Qt::WA_DeleteOnClose);//属性,解决不指定父对象的释放问题,关闭的时候自动释放 33 p->show(); 34 35 } 36 ); 37 //标准对话框 38 QAction *p3=menu->addAction("关于对话框"); 39 connect(p3,&QAction::triggered, 40 [=]() 41 { 42 QMessageBox::about(this,"about","关于Qt"); 43 } 44 ); 45 46 QAction *p4=menu->addAction("问题对话框"); 47 connect(p4,&QAction::triggered, 48 [=]() 49 { 50 int ret=QMessageBox::question(this, 51 "question","Are you ok?", 52 //点击按钮会获得一个返回值 53 QMessageBox::Yes,QMessageBox::Cancel);//可省,带默认按键Yes|No 54 switch(ret) 55 { 56 case QMessageBox::Yes: 57 qDebug()<<"i am ok"; 58 break; 59 case QMessageBox::Cancel: 60 qDebug()<<"i am bad"; 61 break; 62 default: 63 break; 64 } 65 } 66 ); 67 QAction *p5=menu->addAction("文件对话框"); 68 connect(p5,&QAction::triggered, 69 [=]() 70 { 71 QString path=QFileDialog::getOpenFileName( 72 this,"open", "../", 73 "souce(*.cpp *.h);;" 74 "Text(*.txt);;all(*.*)"//可省,但是就无法选择文件格式 75 //在;;后面回车Qt会自动补上"",上面相当于"souce(*.cpp *.h);;Text(*.txt);;all(*.*)" 76 ); 77 qDebug()<<path; 78 79 } 80 );
15)信号槽的扩展
1.一个信号可以连接多个槽函数
槽函数的执行顺序是随机的,不能控制
2.一个槽函数可以被多个信号连接
3.信号可以连接信号
4.信号槽连接成功后,可以断开连接disconnect
5.槽函数可以是lambda表达式