QT入门到实战
一、 Day01
1. 快捷键
注释:ctrl + /
运行:ctrl + r
编译:ctrl + b
字体缩放:ctrl + 鼠标滚轮
查找:ctrl + f
整行移动:ctrl + shift + 上下键
帮助文档:F1
自动对齐:ctrl + i
同名之间.h和.cpp切换:F4
2.对象树
(1)当创建的控件对象在堆区的时候,如果指定的父亲是QObject派生的类或QObject子类派生的类,那么不用管理释放的操作,qt会将对象放入到对象树中,父类窗口释放时,会先释放所有子对象控件。
(2)一定程度上简化了界面的内存回收机制。
3.信号和槽
可以查帮助文档看有哪些信号和槽函数
(1)连接函数:connect
(2)参数:
参数1:信号的发送者
参数2:发送的信号(函数地址)
参数3:信号的接收者
参数4:处理的槽函数(函数地址)
(3)信号机制起到松散耦合的作用
(4)connect(btn,&QPushButton::click,this,&QWidget::close);
4.自定义信号和槽
(1)自定义信号:
i.写到signals下
ii.返回void,只需声明,不需要实现,可有参数,可重载。
(2)自定义槽函数
i.返回void,需要声明在public slot或高版本的public中,可有参数,可重载。
(3)触发信号:
emit 自定义信号;
(4)拓展:
i.信号可以连接信号;
ii.一个信号可以连接多个槽函数;
iii.多个信号可以连接同一个;
iiii.信号和槽函数的参数类型必须一一对应相同;
v.信号和槽函数的参数个数 是不是要一致?信号的参数个数可以多余槽函数个数;
vi.信号槽可以断开,disconnect断开;
(5)qt4的写法:
Connect(信号发送者,signal(信号),信号接收者,slot(槽函数));
优点:参数直观 缺点:不做类型检测;
1.
Class Teacher:public QObject
{
Signal:
Void hungry();
Void hungry(QString foodName);
//自定义两个信号,一个带参,一个不带参
}
2.
Class Student:pulic QObject
{
Public slot:
Void treat();
Void treat(QString foodName);//不带参和带参槽函数
}
Void Student::treat(){
qDebug()<<”请老师吃饭”;
}
Void Student::treat(QString foodName){
qDebug()<<”请老师吃:”<< foodName;
}
3.
class Main:public QObject
{
Public:
Void classIsOver();//用于发送信号的函数
}
Main: Main{
Teacher * te = new Teacher();
Strudent *st = new Student();
//调用不带参的信号,若有重载信号和槽函数,怎样调用错误
//Connect(te,&Teacher::hungry,st,&Student::treat);
//当信号和信号槽发生重载后,必须明确指定调用哪个信号,那个槽函数
//可以使用函数指针
Void (Teacher:: *teacherSignal)(QString) = &Teacher::hungry;
Void (Student::*studentSignal)(QString) = &Strudent::treat;
Connect(te, teacherSignal,st, studentSignal);
//发送信号
classIsOver();
}
Void Main ::classIsOver(){
//发送信号
//调用不参的
emit te->hungry();
//调用带参的
Emit te->hungry(“宫保鸡丁”);
}
5. Lambda表达式
1.[]表示一个匿名函数
2.[=]表示是值传递
3.[&]表示是引用传递
4.() 参数
5.{} 实现体
6.mutable 修饰值传递变量,可以修改拷贝的数据,但改变不了本体。
7.即:返回值 {}
1.单独使用,记得后面加括号。
[btn](){
btn.setText(“Lambda”);
}();
2.做信号槽,当点击按钮时,就会执行函数体
Connect(btn,&QPushButton::clicked,[=](){
btn.setText(“Lambda”);
});
二、Day02
1.QMainWindow
QMainWindow是一个为用户提供主窗口程序的类,包括一个菜单栏(QMenuBar)、多个工具栏(QToolBar)、多个锚接部件(dock widgets)、一个状态栏(status bar)以及一个中心部件(central widget),是许多应用程序的基础,如文本编辑器、图片编辑器等。
1.1 QMenu菜单栏
一个QMainWindow中菜单栏最多有一个
如下为创建过程:
//创建菜单栏,一个窗口只有一个菜单栏
QMenuBar *bar = new QMenuBar();//menu会自动加入对象树
//将菜单栏放入窗口
setMenuBar(bar);
//创建菜单
QMenu *openMenu = new QMenu("打开");
QMenu *editMenu = new QMenu("编辑");
//添加到菜单栏
bar->addMenu(openMenu);
bar->addMenu(editMenu);
//添加菜单项
QAction *fileAction = new QAction("打开文件");
QAction *folderAction = new QAction("打开文件夹");
openMenu->addAction(fileAction);
openMenu->addSeparator();//添加分割线
openMenu->addAction(folderAction);
2.2 QToolBar工具栏
工具栏QToolBar可以有多个
以下为创建过程:
//添加工具栏
QToolBar *toolBar =new QToolBar(this);//默认没有加入对象树,得手动加入
//设置默认在左边
addToolBar(Qt::LeftToolBarArea,toolBar);
//设置是否可以悬浮
toolBar->setFloatable(false);
//设置只能在左右两边
toolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);
//设置是否可以移动,若为假,那么上面的都失效
toolBar->setMovable(true);
//工具栏中添加控件
QAction *welcomeAction = toolBar->addAction("欢迎");
toolBar->addSeparator();
QAction *editAction = toolBar->addAction("编辑");
2.3 QStatusBar 状态栏
状态栏最多一个
//状态栏
QStatusBar *statusBar = new QStatusBar(this);
setStatusBar(statusBar);
//添加提示信息
QLabel *labelLeft = new QLabel("左边提示信息",this);
QLabel *labelRight = new QLabel("右边提示信息",this);
statusBar->addWidget(labelLeft);
statusBar->addPermanentWidget(labelRight);
2.4 QDockWidget锚接控件
锚接控件即浮动窗口,可以有多个
//锚接部件(浮动窗口) 可以有多个
QDockWidget *dock = new QDockWidget("浮动窗口",this);
addDockWidget(Qt::BottomDockWidgetArea,dock);
2.5 central widget核心部件
核心部件只能有一个
//中心部件添加 只能有一个
QTextEdit *edit = new QTextEdit(this);
setCentralWidget(edit);
2. 资源文件
1.将图片文件夹拷贝到项目目录下
2.右键项目->添加新文件->Qt ->Qt resource File给资源文件取名为res
3.项目生成res.qrc文件,右键资源文件->open in editor 编辑资源
4.添加前缀,添加文件
5.代码中使用“: +前缀名+文件名”调用图片
3. 模态和非模态对话框
1.模态对话框:不可以对其他对话框进行操作 阻塞
QDialog dlg(this);
dlg.exec();
2.非模态对话框:可以对其他窗口进行操作
(1)QDIalog dlg(this) 这样创建会一闪而过。
(2)所以得创建在堆区:
QDialog dlg(this);
dlg->show();
dlg->setAttribute(Qt::WA_DeleteOnClose);//设置关闭就释放
4.消息对话框
二、 day03
1. 自定义控件
为什么要实现自定义控件?
因为有时候系统提供的控件满足不了我们开发程序所需,比如需要实现一个很炫的进度条等时,就需要自定义控件。
(1) 新建一个widget的带ui的子类,在ui上添加相应控件,并实现控件事件。
(2) 在需要用的界面上添加一个widget容器,然后右键->提升为,将自定义的控件类名填入,确认。
(3) 运行程序,界面就显示了刚自定义的控件。
注意:提升的控件和被提升的控件类型必须一致,即基类必须一致;如本例的都是widget,还有都是label等。
显示自定义控件的界面:
自定义控件:
运行结果
2. 鼠标事件
enterEvent:鼠标进入事件
leaveEvent:鼠标离开事件
mousePressEvent:鼠标按下
mouseReleaseEvent:鼠标释放
mouseMoveEvent:鼠标移动
多看apt查询具体类用法
3. 定时器
3.1 timerEvent事件实现
3.1.1实现QObject的timerEvent事件
只要是QObject的子类,都可以实现该方法
[virtual protected] void QObject::timerEvent(QTimerEvent *event);
3.1.2. int QObject::startTimer(int interval)触发timerEvent事件
Int timerId1 = startTimer(100);//启动定时器,参数为毫秒,返回定时器id
Int timerId2 = startTimer(200);//可以启动多个定时器,用定时器id区分
如:
void QObject::timerEvent(QTimerEvent *event){
if(event->timerId() == timerId1){
qDebug()<<”timer1”;
}else if(event->timerId() == timerId2){
qDebug()<<”timer2”;
}
}
3.2 QTimer类实现
利用定时器类QTimer实现定时器功能,相比事件实现,推荐使用这种实现方式,因为这个是一个定时器实现一个功能,定时器发出timeout信号,槽函数实现具体内容,不需要timerEvent使用timerId判断是那个定时器。
#include<QTimer>
QTimer *timer = new QTimer();
Timer->start(1000);//开启定时器
//lambda表达式实现,或者声明槽函数实现,timer具体还有哪些方法,查看qt api;
Connect(timer,QTimer::timeout,[](){
qDebug()<<”timer”;
});
4.Event事件分发器
事件分发器用于对所有事件进行分发,可以实现event方法进行事件的拦截(不推荐),当event返回true时,表示用户自己处理这个事件,不在向下分发。
拦截实例:
bool QObject::event(QEvent *e){
if(e->type() == QEvent::MouseButtonPress){
//用户自己处理
qDebug()<<”拦截鼠标按钮向下按事件mouseReleaseEvent(QMouseEvent *event)”;
return true;//返回true时,那个是实现的鼠标按钮向下按事件就没有用了
}
Return QObject::event(e);//交给object处理
}
5. 事件过滤器
在程序将事件分发到事件分发器前,可以通过事件拦截器拦截事件。
实现方式:
- 给控件安装事件过滤器
- 重写event Filter函数
实列:
.h
Bool eventFilter(QObject *,QEvent *);
.cpp
className:: className{
//安装过滤器
This->ui->label->installEventFilter(this);//父类安装
}
bool className::eventFilter(QObject *obj,QEvent *e){
if(obj == this->ui->label){
if(e->type() == QEvent::MouseButtonPress){
qDebug()<<”拦截到label的鼠标按下事件”;
}
return true;
}
//其他事件交给父类className处理
Return className::eventFilter(obj,e);
}
6.绘图
6.1 绘图事件
绘图事件painterEvent实现后会自己调用,声明一个painter画家,并指定画图设备,然后就可以在设备上画图:
.h
Void painterEvent((QPaintEvent *event));
.cpp
void MainWindow::paintEvent(QPaintEvent *event){
QPainter painter(this);
//设置画笔
QPen pen(QColor(255,0,0));
pen.setWidth(2); //设置笔宽
pen.setStyle(Qt::DotLine);//设置风格为画点
painter.setPen(pen);//画家使用这支笔
//设置画刷
QBrush brush(Qt::cyan);
painter.setBrush(brush);
//画椭圆
painter.drawEllipse(QPoint(100,100),50,50);
//画线
painter.drawLine(QPoint(0,0),QPoint(100,100));
//还可以话很多painter自带的图形
}
6.2painter高级设置
设置 抗锯齿能力 但画图效率低
Painter.setRenderHint(QPainter::Antialiasing);
移动画家,图片x移动100,y移动0
Painater.translate(100,0);
保存画家状态
Painter.save();
还原画家状态
Painter.restore();
6.3绘图设备
绘图设备是指继承QPainterDevice的子类,qt一共提供了四个这样的类:
QPixmap、QBitmap、PImage和QPicture。
QPixmap:专门为图像在屏幕的显示上做了优化
QBitmap是QPixmap的子类,它的色深限度为1,可以用QPixmap的isQBitmap函数来确定一个QPixmap是不是一个QBitmap。
QImage专门为图像的像素级访问做了优化
QPicture则可以记录和重现QPicture的各条命令