1.Qt简介
Qt是一个跨平台的C++图形用户界面应用程序框架,是完全面向对象的
Qt开发案例:谷歌地图,WPS,Linux桌面环境
1.1 创建第一个Qt程序
(1)点击创建项目后,选择项目路径以及给项目起名称
(2)名称 — 不能有中文,不能有空格
(3)路径 — 不能有中文路径
(4)默认创建有窗口类,myWidget,基类有三种选择:QWidget,QMainWindow,QDialog
(5)main函数中:
- QApplication a 应用程序对象,有且仅有一个
- myWidget w; 实例化窗口对象
- w.show ( ) 调用show函数,显示窗口
- return a.exec ( ) 让应用程序对象进入消息循环机制中,代码阻塞到当前行
#include "mywidget.h"
#include <QApplication> //包含一个应用程序类的头文件
//main:程序入口 argc:命令行变量的数量 argv:命令行变量的数组
int main(int argc, char *argv[])
{
//a:应用程序对象,在Qt中,应用程序对象,有且仅有一个
QApplication a(argc, argv);
//w:窗口对象 myWidget父类-> QWidget
myWidget w;
//窗口对象默认不会显示,必须要调用show方法显示窗口
//show以顶层方式弹出窗口控件
w.show();
//让应用程序对象进入消息循环
//让代码阻塞到这行
return a.exec();
}
在 mywidget.h 中,Q_OBJECT是一个宏,允许类中使用信号和槽的机制
想要在Qt中输出内容,需要加头文件 #include<QDebug>,之后可以在内部用 qDebug()<<"输出的内容"; 进行内容的输出
1.2 命名规范与快捷键
命名规范:
类名:首字母大写,单词和单词之间首字母大写
函数名,变量名称:首字母小写,单词和单词之间首字母大写
快捷键:
注释:ctrl + /
运行:ctrl + r
编译:ctrl + b
字体缩放: ctrl + 鼠标滚轮
查找:ctrl + f
整行移动:ctrl + shift + 上或下的箭头
自动对齐:ctrl + i
同名之间 .h 和 .cpp 切换:Fn + F4
帮助文档:鼠标移动到想要查询的单词处,Fn + F1,如果想要退出按下 Esc;或者点击Qt中的帮助按钮;或者在安装的bin目录下可以点击
2. 按钮创建,对象树与坐标系
2.1 按钮创建
创建时在mywidget.cpp中进行创建
创建时需要添加按钮控件的头文件 #include<QPushButton>
2.1.1 按钮控件常用API
创建按钮: QPushButton * btn = new QPushButton;
设置父亲:btn->setParent (this);
设置文本:btn->setText ("文字");
设置位置:btn->move (宽,高);
重新指定窗口大小:resize (宽,高);
按钮的大小:btn->resize (宽,高);
设置窗口标题:setWindowTitle("标题");
设置窗口固定大小:setFixedSize(宽,高);
#include "mywidget.h"
#include<QPushButton>
myWidget::myWidget(QWidget *parent)
: QWidget(parent)
{
//创建一个按钮
QPushButton *btn= new QPushButton;
//让btn对象依赖在 mywidget窗口中
btn->setParent(this);
//显示文本
btn->setText("第一个按钮");
//创建第二个按钮 会按照控件的大小创建窗口
QPushButton *btn2 = new QPushButton("第二个按钮",this);
//移动btn2按钮
btn2->move(100,100);
//按钮重置大小
btn2->resize(50,30);
//重置窗口
resize(600,400);
//设置固定窗口大小
setFixedSize(600,400);
//设置窗口标题
setWindowTitle("第一个窗口");
}
myWidget::~myWidget()
{
}
2.2 对象树
当创建的对象在堆区时候,如果指定的父亲是QObject派生下来的类或者QObject子类派生下来的类,可以不用管理释放的操作,将对象会放入到对象树中
一定程度上简化了内存回收机制
2.3 Qt窗口坐标系
坐标体系:
以左上角为原点(0,0),X向右增加,Y向下增加
对于嵌套窗口,其坐标是相对于父窗口来说的
3. 信号和槽机制
需要使用 connect()函数;
connect(信号的发送者,发送的信号,信号的接收者,信号的处理(槽函数))
Qt4版本写法:connect(信号的发送者,发送的信号 SIGNAL(信号),信号的接收者,信号的处理(槽函数)SLOT(槽函数))
Qt4版本写法的优点是参数直观,缺点是编译器不会检测参数类型
信号槽的优点:松散耦合,即信号的发送端和接收端本身是没有关联的,通过connect连接将两端耦合在一起
实现点击自己创建的按钮,关闭窗口:
//创建自己按钮的对象
MyPushButton *mybtn = new MyPushButton;
mybtn->setText("我自己的按钮");
mybtn->move(300,0);
mybtn->setParent(this);
//需求 点击我的按钮,关闭窗口
//参数1:信号的发送者,参数2:发送的信号(函数的地址),参数3:信号的接收者,参数4:信号的处理(槽函数)
connect(mybtn,&QPushButton::clicked,this,&QWidget::close);
//&QPushButton中的&可加可不加,&QWidget中的&也一样
3.1 自定义信号和槽
3.1.1 自定义信号和槽的写法
自定义信号:
写到signals下,函数的返回值是void,需要声明,不需要实现,函数可以有参数,可以重载
自定义槽函数:
写到 public slot 下或者 public 下或者全局函数,函数的返回值是void,需要声明也需要实现,函数可以有参数,可以重载
触发自定义信号:emit 自定义信号
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//创建老师对象
this->zt=new Teacher(this);
//创建学生对象
this->st=new Student(this);
//建立连接
connect(zt,&Teacher::hungry,st,&Student::treat);
//调用函数
classOver();
}
void Widget::classOver(){
//触发信号
emit zt->hungry();
}
Widget::~Widget()
{
delete ui;
}
3.1.2 重载问题
当自定义信号和槽出现重载时,需要利用函数指针,明确指向函数的地址
//函数指针 指向 函数地址
void(Teacher::*teacherSignal)(QString)=&Teacher::hungry;
void(Student::*studentSlot)(QString)=&Student::treat;
//连接带参数的信号和槽
connect(zt,teacherSignal,st,studentSlot);
classOver();
3.1.3 QString 转成 char *
先转成 QByteArray,即 QString类型.toUtf8(),在转成 char * ()
void Student::treat(QString foodName){
qDebug()<<"吃饭吃:"<<foodName.toUtf8().data();
}
3.1.4 信号连接信号与断开信号
断开信号使用 disconnect()函数
//点击一个 下课按钮,再触发下课
QPushButton *btn = new QPushButton("下课",this);
//connect(btn,&QPushButton::clicked,this,&Widget::classOver);
//无参信号连接
void(Teacher::*teacherSignal2)(void)=&Teacher::hungry;
void(Student::*studentSlot2)(void)=&Student::treat;
connect(zt,teacherSignal2,st,studentSlot2);
//信号连接信号
connect(btn,&QPushButton::clicked,zt,teacherSignal2);
//断开信号
disconnect(zt,teacherSignal2,st,studentSlot2);
3.1.5 拓展
信号可以连接信号
一个信号可以连接多个槽函数
多个信号可以连接同一个槽函数
信号和槽函数的参数,必须类型一一对应
在信号和槽函数的参数个数中,信号的参数个数可以多于槽函数的参数个数
4. Lambda 表达式
C++11中的Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作
Lambda表达式最常用的方式:[ = ]( ){ };
- [ ],标识符,匿名函数,[ ]中可以填入 = 号,表示值传递;可以填入 & 号,表示引用传递
- ( ),参数列表
- { },实现体
mutable修饰值传递变量,可以修改拷贝出的数据,改变不了本体
返回值 [ ]( ) -> int { }
int ret = []()->int{
return 1000;
}();
qDebug()<<"ret = "<<ret;
槽函数可以使用Lambda表达式
//利用lambda表达式,实现点击按钮,关闭窗口
QPushButton *btn2 = new QPushButton;
btn2->setText("关闭");
btn2->move(300,50);
btn2->setParent(this);
connect(btn2,&QPushButton::clicked,this,[=](){
this->close();
emit zt->hungry("宫保鸡丁");
});
5. QMainWindow
QMainWindow是一个为用户提供主窗口程序的类,包含一个菜单栏(menu bar),多个工具栏(tool bars),多个锚接部件或者叫浮动窗口(dock widgets),一个状态栏(status bar)以及一个中心部件(central widget),是许多应用程序的基础
5.1 菜单栏
使用时添加头文件 #include <QMenuBar>
菜单栏最多只能有一个
创建菜单栏:QMenuBar *bar = MenuBar();
将菜单栏放入窗口中:setMenuBar(bar);
创建菜单:QMenu * fileMenu = bar->addMenu("文件");
创建菜单项:QAction * newAction = fileMenu->addAction("新建");
添加分割线: fileMenu->addSeparator();
5.2 工具栏
使用时添加头文件 #include <QToolBar>
工具栏可以有多个
创建工具栏:QToolBar * toolbar = new QToolBar(this);
将工具栏放入窗口:addToolBar(默认停靠位置 ,toolBar); //如停靠左边为Qt::LeftToolBarArea
其他设置见后续代码
5.3 状态栏
使用时添加头文件 #include <QStatusBar>
状态栏最多有一个
创建状态栏:QStatusBar *stBar = statusBar();
将状态栏放入到窗口:setStatusBar(stBar);
其他设置见后续代码
5.4 锚接部件(浮动窗口)
使用时添加头文件 #include <QDockWidget>
浮动窗口可以有多个
创建锚接部件:QDockWidget * dockwidget = new QDockWidget("浮动",this);
放入窗口:addDockWidget(Qt::BottomDockWidgetArea,dockwidget);
5.5 中心部件
使用时添加头文件 #include <QTextEdit>
中心部件只能有一个
创建中心部件:QTextEdit *edit = new QTextEdit(this);
放入窗口:setCentralWidget(edit);
5.6 记忆方法与例子
如果部件只能有一个,则放入窗口用set()方法,若可以有许多个,则放入窗口用add()方法
#include "mainwindow.h"
#include <QMenuBar>
#include <QToolBar>
#include <QDebug>
#include <QPushButton>
#include <QStatusBar>
#include <QLabel>
#include <qdockwidget.h>
#include <QTextEdit>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
resize(800,500);
//菜单栏,只能最多有一个
//菜单栏创建
QMenuBar *bar =menuBar();
//把菜单栏放入窗口中
setMenuBar(bar);
//创建菜单
QMenu *filemenu = bar->addMenu("文件");
QMenu *editmenu = bar->addMenu("编辑");
//创建菜单项
QAction * newAction = filemenu->addAction("新建");
//添加分割线
filemenu->addSeparator();
QAction * openAction = filemenu->addAction("打开");
//工具栏 可以有多个
QToolBar * toolBar = new QToolBar(this);
//将工具栏放到窗口中 指定在左边
addToolBar(Qt::LeftToolBarArea ,toolBar);
//后期设置,只允许左右停靠
toolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);
//设置浮动
toolBar->setFloatable(false);
//设置移动(总开关)
toolBar->setMovable(false);
//工具栏中可以设置内容
toolBar->addAction(newAction);
//添加分割线
toolBar->addSeparator();
toolBar->addAction(openAction);
//工具栏中添加控件
QPushButton *btn = new QPushButton("aa",this);
toolBar->addWidget(btn);
//状态栏,最多有一个
QStatusBar *stBar = statusBar();
//放入窗口中
setStatusBar(stBar);
//放标签控件
QLabel *lable = new QLabel("提示信息",this);
stBar->addWidget(lable);
QLabel *lable2 = new QLabel("右侧提示信息",this);
stBar->addPermanentWidget(lable2);
//锚接部件(浮动窗口)可以有多个
QDockWidget * dockwidget = new QDockWidget("浮动",this);
//放入窗口
addDockWidget(Qt::BottomDockWidgetArea,dockwidget);
//设置后期停靠区域,只允许上下
dockwidget->setAllowedAreas( Qt::TopDockWidgetArea| Qt::BottomDockWidgetArea);
//设置中心部件 只能有一个
QTextEdit *edit = new QTextEdit(this);
setCentralWidget(edit);
}
MainWindow::~MainWindow()
{
}
6. 资源文件
6.1 添加资源文件
- 将图片文件拷贝到项目位置下
- 右键项目 -> 添加新文件 -> Qt -> Qt recourse File -> 给资源文件起名
- res 生成 res.qrc
- 右击 res.qrc,选择open in editor,编辑资源
- 添加前缀,添加文件
6.2 使用资源文件
使用 " :+前缀名 + 文件名 ";
ui->actionnew->setIcon(QIcon(":/11.jpg"));
7. 对话框
使用时添加头文件 #include <QDialog>
7.1 对话框分类
对话框分为模态对话框和非模态对话框
7.1.1 模态对话框
具有阻塞功能,即不可以对其他窗口进行操作
创建模态对话框:QDialog dlg(this);
实现阻塞:dlg.exec();
7.1.2 非模态对话框
可以对其他窗口进行操作
创建非模态对话框: QDialog *dlg2=new QDialog(this); 为防止一闪而过,创建到堆区
展示非模态对话框:dlg2->show();
防止没有删除对话框,造成资源溢出:dlg2->setAttribute(Qt::WA_DeleteOnClose);
//点击新建按钮 弹出一个对话框
connect(ui->actionnew,&QAction::triggered,[=](){
//模态对话框创建 阻塞功能(不可以对其他窗口进行操作)
// QDialog dlg(this);
// dlg.resize(200,100);
// dlg.exec();
// qDebug()<<"模态对话框弹出";
//非模态对话框
QDialog *dlg2=new QDialog(this);
dlg2->resize(200,100);
dlg2->show();
dlg2->setAttribute(Qt::WA_DeleteOnClose); //55号 属性
qDebug()<<"非模态对话框弹出";
7.2 消息对话框
使用时添加头文件 #include <QMessageBox>
消息对话框是一个模态对话框
消息对话框有 错误对话框,信息对话框,提问对话框,警告对话框
创建对话框:QMessageBox : : 静态成员函数
静态成员函数中的参数:参数1:父亲; 参数2:标题; 参数3:提示内容; 参数4:按键类型; 参数5:默认关联回车按键
7.2.1 错误对话框
错误对话框:QMessageBox::critical(this,"critical","错误");
7.2.2 信息对话框
信息对话框 :QMessageBox::information(this,"info","信息");
7.2.3 提问对话框
提问对话框:if (QMessageBox::Save == QMessageBox::question(this,"quess","提问",QMessageBox::Save | QMessageBox::Cancel,QMessageBox::Cancel)){
qDebug()<<"选择的是保存"; }else{
qDebug()<<"选择的是取消"; }
提问对话框的返回值也是 StandardButton类型,利用返回值判断用户的输入
7.2.4 警告对话框
警告对话框: QMessageBox::warning(this,"warning","警告");
7.2.5 例子
//消息对话框-错误对话框
QMessageBox::critical(this,"critical","错误");
//消息对话框-信息对话框
QMessageBox::information(this,"info","信息");
//消息对话框-提问对话框
//参数1:父亲;参数2:标题;参数3:提示内容;参数4:按键类型;参数5:默认关联回车按键
if (QMessageBox::Save == QMessageBox::question(this,"quess","提问",QMessageBox::Save | QMessageBox::Cancel,QMessageBox::Cancel)){
qDebug()<<"选择的是保存";
}else{
qDebug()<<"选择的是取消";
}
//消息对话框-警告对话框
QMessageBox::warning(this,"warning","警告");
7.3 其他标准对话框
7.3.1 颜色对话框
使用时添加头文件 #include <QColorDialog>
获取颜色:QColorDialog::getColor()
7.3.2 文件对话框
使用时添加头文件 #include <QFileDialog>
获取文件: QFileDialog::getOpenFileName(父亲,标题,默认路径,过滤文件);
7.3.3 字体对话框
使用时添加头文件 #include <QFontDialog>
获取字体:QFontDialog::getFont(字体,字号);
7.3.4 例子
//其他标准对话框
//颜色对话框
// QColor color = QColorDialog::getColor(QColor(255,0,0));
// qDebug()<<"r = "<<color.red()<<" g = "<<color.green()<<" b= "<<color.blue();
//文件对话框
//参数1:父亲;参数2:标题;参数3:默认打开路径;参数4:过滤文件格式
// QString str = QFileDialog::getOpenFileName(this,"打开文件","C:\\***\\***\\Desktop","(*.txt)");
// qDebug()<<str;
//字体对话框
bool flag;
QFont font = QFontDialog::getFont(&flag,QFont("楷体",18));
qDebug()<<"字体:"<<font.family().toUtf8().data()<<" 字号:"<<font.pointSize()<<" 是否加粗:"<<font.bold()<<" 是否倾斜:"<<font.italic();
在界面布局中,默认窗口和控件之间有9间隙,可以调整 layoutLeftMargin;可以利用弹簧去布局
8. 控件
8.1 按钮组
QPushButton:常用按钮
QToolButton:工具按钮,用于显示图片,若图片想要显示文字,则需要修改风格toolButtonStyle,凸起风格为autoRaise
RadioButton:单选按钮,设置默认为 ui->rBtnMan->setChecked(true);
CheckBox:多选按钮,有三种监听状态:2代表选中,1代表半选,0代表未选中
8.2 QListWidget控件
QListWidget是列表容器
利用 QListWidgetItem *item 书写一行内容到列表中
书写一行内容,并添加到列表中,设置为居中方式:
QListWidgetItem *item = new QListWidgetItem("锄禾日当午");
ui->listWidget->addItem(item);
item->setTextAlignment(Qt::AlignHCenter);
利用 addItems 一次性添加整个诗的内容
QStringList list;
list<<"锄禾日当午"<<"汗滴禾下土";
ui->listWidget->addItems(list);
8.3 QTreeWidget树控件
设置头:ui->treeWidget->setHeaderLabels(QStringList()<<"英雄"<<"英雄介绍"); //匿名对象
创建根节点:QTreeWidgetItem * liItem = new QTreeWidgetItem(QStringList()<<"力量");
添加根节点到树控件上:ui->treeWidget->addTopLevelItem(liItem);
添加子节点:liItem->addChild(l11);
//树控件的使用
//设置水平头
ui->treeWidget->setHeaderLabels(QStringList()<<"英雄"<<"英雄介绍"); //匿名对象
QTreeWidgetItem * liItem = new QTreeWidgetItem(QStringList()<<"力量");
QTreeWidgetItem * minItem = new QTreeWidgetItem(QStringList()<<"敏捷");
QTreeWidgetItem * zhiItem = new QTreeWidgetItem(QStringList()<<"智力");
//加载顶层的节点
ui->treeWidget->addTopLevelItem(liItem);
ui->treeWidget->addTopLevelItem(minItem);
ui->treeWidget->addTopLevelItem(zhiItem);
//追加子节点
QTreeWidgetItem * l11 = new QTreeWidgetItem(QStringList()<<"来来来啊啊");
liItem->addChild(l11);
8.4 QTableWidget控件
QTableWidget是表格控件
设置列数:ui->tableWidget->setColumnCount(3);
设置水平表头 :ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<"姓名"<<"性别"<<"年龄");
设置行数:ui->tableWidget->setRowCount(5);
设置正文:ui->tableWidget->setItem(0,0,new QTableWidgetItem("aa"));
//表格控件实现
//设置列数
ui->tableWidget->setColumnCount(3);
//设置水平表头
ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<"姓名"<<"性别"<<"年龄");
//设置行数
ui->tableWidget->setRowCount(5);
//设置正文
//ui->tableWidget->setItem(0,0,new QTableWidgetItem("aa"));
QStringList nameList;
nameList<<"aa"<<"bb"<<"cc"<<"dd"<<"ee";
QList<QString> sexList;
sexList<<"man"<<"woman"<<"man"<<"woman"<<"man";
for(int i=0;i<5;i++){
int col=0;
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(nameList[i]));
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(sexList.at(i)));
//int转QString
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(QString::number(i+18)));
}
8.5 其他常用控件介绍
栈控件:stackedWidget
ui->stackedWidget->setCurrentIndex(1);
下拉框:ui->comboBox->addItem("奔驰");
显示图片:ui->lbl_image->setPixmap(QPixmap(""/image/xxx.png"));
显示动图,gif图片:QLable
ui->lbl_movie->setMovie(movie);
movie->start(); //图片动起来
9. 事件
9.1 鼠标事件
鼠标进入事件:enterEvent
鼠标离开事件:leaveEvent
鼠标按下:mousePressEvent(QMouseEvent *ev)
鼠标释放:mouseReleaseEvent(QMouseEvent *ev)
鼠标移动:mouseMoveEvent(QMouseEvent *ev)
ev->x() 表示x坐标 ev->y()表示y坐标
ev->button()可以判断所有按键 Qt::LeftButton Qt::RightButton
ev->buttons()判断组合按键,判断move时候的左右键,结合&操作符
格式化字符串:QString("鼠标释放,x=%1,y=%2,globalX=%3,globalY=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
#include "mylable.h"
#include <QDebug>
#include <QMouseEvent>
myLable::myLable(QWidget *parent) : QLabel(parent)
{
//设置鼠标追踪状态
setMouseTracking(true);
}
//鼠标进入事件
void myLable::enterEvent(QEvent *event){
qDebug()<<"鼠标进入";
}
//鼠标离开事件
void myLable::leaveEvent(QEvent *){
qDebug()<<"鼠标离开";
}
//鼠标按下
void myLable::mousePressEvent(QMouseEvent *ev){
//当鼠标左键按下 提示信息
if(ev->button()==Qt::LeftButton){
QString str = QString("鼠标按下,x=%1,y=%2,globalX=%3,globalY=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug()<<str;
}
}
//鼠标释放
void myLable::mouseReleaseEvent(QMouseEvent *ev){
QString str = QString("鼠标释放,x=%1,y=%2,globalX=%3,globalY=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug()<<str;
}
//鼠标移动
void myLable::mouseMoveEvent(QMouseEvent *ev){
QString str = QString("鼠标移动,x=%1,y=%2,globalX=%3,globalY=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug()<<str;
}
9.2 定时器
9.2.1 定时器1
利用事件:void timerEvent(QTimerEvent *);
启动定时器:startTimer(1000),单位是毫秒
timerEvent的返回值是定时器的唯一标识,可以和ev->timerId作比较
9.2.2 定时器2
利用定时器类 QTimer,使用时添加头文件 #include <QTimer>
创建定时器对象:QTimer *timer = new QTimer(this);
启动定时器:timer->start(500); 单位是毫秒
每隔一定毫秒,发送信号 timeout,进行监听
暂停:timer->stop();
#include "widget.h"
#include "ui_widget.h"
#include <QTimer> //定时器的类
#include <QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//启动定时器
//参数1,代表间隔,单位是毫秒
id1 = startTimer(1000);
id2 = startTimer(2000);
//定时器第二种方式
QTimer *timer = new QTimer(this);
//启动定时器
timer->start(500);
connect(timer,&QTimer::timeout,[=](){
static int num=1;
//label4 每隔0.5秒+1
ui->label_4->setText(QString::number(num++));
});
//点击暂停按钮,实现定时器暂停
connect(ui->btn,&QPushButton::clicked,[=](){
timer->stop();
});
}
//重写定时器事件
void Widget::timerEvent(QTimerEvent * ev){
if(ev->timerId()==id1){
static int num=1;
//label2 每隔1秒+1
ui->label_2->setText(QString::number(num++));
}
if(ev->timerId()==id2){
//label3 每隔2秒+1
static int num2=1;
ui->label_3->setText(QString::number(num2++));
}
}
Widget::~Widget()
{
delete ui;
}
9.3 event 事件分发器
用途为用于事件的分发,也可以做拦截的操作,但是不建议
函数为:bool event(QEvent *e); 返回值如果是true,代表用户处理这个事件,不向下进行分发
//通过event事件分发器,拦截鼠标按下事件
bool myLable::event(QEvent *e){
if(e->type()==QEvent::MouseButtonPress){
//类型转换
QMouseEvent *ev = static_cast<QMouseEvent *>(e);
QString str = QString("EVENT函数中:鼠标移动,x=%1,y=%2,globalX=%3,globalY=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug()<<str;
return true;//代表用户自己处理这个事件,不向下分发
}
//其他事件,交给父类处理,默认处理
return QLabel::event(e);
}
9.4 事件过滤器
通过事件过滤器,可以在程序分发到event事件之前再做一次高级拦截
使用时的两个步骤:
- 给控件安装事件过滤器
- 重写 eventfilter 事件
//给label1安装事件过滤器
//步骤1,安装过滤器
ui->label->installEventFilter(this);
//步骤2,重写事件
}
//步骤2,重写事件
bool Widget::eventFilter(QObject *obj,QEvent *e){
if(obj==ui->label){
if(e->type()==QEvent::MouseButtonPress){
//类型转换
QMouseEvent *ev = static_cast<QMouseEvent *>(e);
QString str = QString("事件过滤器中:鼠标移动,x=%1,y=%2,globalX=%3,globalY=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug()<<str;
return true;//代表用户自己处理这个事件,不向下分发
}
}
return QWidget::eventFilter(obj,e);
}
9.5 QPainter绘图
使用时添加头文件 #include <QPainter>
9.5.1 绘图事件
绘图事件定义为:void Widget::paintEvent(QPaintEvent *);
声明一个画家对象:QPainter painter(this); this指定绘图设备
设置画笔:QPen pen(QColor(255,0,0));
设置画刷: QBrush brush(Qt::green);
//绘图事件
void Widget::paintEvent(QPaintEvent *){
//实例化画家对象 this指定的是绘图设备
QPainter painter(this);
//设置画笔
QPen pen(QColor(255,0,0));
//设置画笔宽度
pen.setWidth(3);
//设置画笔风格
pen.setStyle(Qt::DotLine);
//画家使用这个笔
painter.setPen(pen);
//设置画刷
QBrush brush(Qt::green);
//设置画刷风格
brush.setStyle(Qt::Dense7Pattern);
//画家使用画刷
painter.setBrush(brush);
//画线
painter.drawLine(QPoint(0,0),QPoint(100,100));
//画圆
painter.drawEllipse(QPoint(100,100),100,50);
//画矩形
painter.drawRect(QRect(20,20,50,50));
//画文字
painter.drawText(QRect(10,200,300,50),"好好学习,天天向上");
}
9.5.2 绘图高级设置
抗锯齿操作:painter.setRenderHint(QPainter::Antialiasing); 但存在效率低的问题
对画家进行移动: painter.translate(100,0);
保存画家状态:painter.save();
还原画家保存状态:painter.restore();
QPainter painter(this);
// painter.drawEllipse(QPoint(100,50),50,50);
// //设置抗锯齿能力 隐患:效率较低
// painter.setRenderHint(QPainter::Antialiasing);
// painter.drawEllipse(QPoint(200,50),50,50);
painter.drawRect(QRect(20,20,50,50));
//移动画家
painter.translate(100,0);
//保存画家状态
painter.save();
painter.drawRect(QRect(20,20,50,50));
painter.translate(100,0);
//还原画家保存状态
painter.restore();
painter.drawRect(QRect(20,20,50,50));
9.5.3 手动调用绘图事件
如果想手动调用绘图事件,利用 update();
利用画家画图片:painter.drawPixmap(x坐标,y坐标,QPixmap("图片路径"));
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//点击移动按钮,移动图片
connect(ui->pushButton,&QPushButton::clicked,[=](){
posX+=15;
//如果要手动调用绘图事件,用update更新
update();
});
}
void Widget::paintEvent(QPaintEvent *){
//利用画家画资源图片
QPainter painter(this);
//如果超出屏幕,从0开始
if(posX>this->width()){
posX=0;
}
painter.drawPixmap(posX,0,QPixmap(":/11.jpg"));
}
9.5.4 绘图设备
绘图设备是指继承 QPainterDevice 的子类
(1). QPixmap
使用时添加头文件 #include <QPixmap>
QPixmap 对不同平台做了显示的优化
使用绘图设备:QPixmap pix(300,300);
填充颜色:pix.fill(Qt::white);
利用画家往 pix 上画画:QPainter painter(&pix);
保存路径:pix.save("E:\\pix.png");
(2). QImage
使用时添加头文件 #include <QImage>
QImage可以对像素进行访问
使用绘图设备:QImage img(300,300,QImage::Format_RGB32);
其他流程和QPixmap一样
可以对像素进行修改:img.setPixel(i,j,value);
(3). QPicture
使用时添加头文件 #include <QPicture>
QPicture用于记录和重现指令
使用绘图设备:QPicture pic;
保存:pic.save("E:\\pic.cm"); //可以使用任意后缀名
重现:利用画家可以重现:painter.drawPicture(0,0,pic);
#include "widget.h"
#include "ui_widget.h"
#include <QPixmap>
#include <QPainter>
#include <QImage>
#include <QPicture>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// //Pixmap绘图设备
// QPixmap pix(300,300);
// //填充颜色
// pix.fill(Qt::white);
// //声明画家
// QPainter painter(&pix);
// painter.setPen(QPen(Qt::green));
// painter.drawEllipse(QPoint(150,150),100,100);
// //保存
// pix.save("E:\\pix.png");
//QImage绘图设备 可以对像素进行访问
// QImage img(300,300,QImage::Format_RGB32);
// img.fill(Qt::white);
// QPainter painter(&img);
// painter.setPen(QPen(Qt::blue));
// painter.drawEllipse(QPoint(150,150),100,100);
// //保存
// img.save("E:\\pix.png");
//QPicture绘图设备 可以记录和重现绘图指令
QPicture pic;
QPainter painter;
painter.begin(&pic); //开始往pic上画
painter.setPen(QPen(Qt::cyan));
painter.drawEllipse(QPoint(150,150),100,100);
painter.end(); //结束画画
//保存到磁盘
pic.save("E:\\pic.cm");
}
//绘图事件
void Widget::paintEvent(QPaintEvent *){
//利用QImage对像素进行修改
// QPainter painter(this);
// QImage img;
// img.load(":/22.jpg");
// //修改像素点
// for(int i=50;i<100;i++){
// for(int j=50;j<100;j++){
// QRgb value=qRgb(255,0,0);
// img.setPixel(i,j,value);
// }
// }
// painter.drawImage(0,0,img);
//重现QPicture的绘图指令
QPainter painter(this);
QPicture pic;
pic.load("E:\\pic.cm");
painter.drawPicture(0,0,pic);
}
Widget::~Widget()
{
delete ui;
}
10. 文件操作
利用 QFile 进行读写操作,使用时添加头文件 #include <QFile>
使用方式:QFile file(文件路径);
10.1 读操作
读取文件:file.open(打开方式); 如只读表示为 QIODevice::ReadOnly
全部读取:QByteArray array = file.readAll();
按行读取:file.readLine()
判断是否读到文件末尾:file.atEnd()
读的默认支持编码格式为 utf-8
若读的是gbk文件:
QTextCodec *codec = QTextCodec::codecForName("gbk");
ui->textEdit->setText(codec->toUnicode(array));
使用完之后需要将文件对象关闭,即file.close();
10.2 写操作
以追加的方式进行写文件:file.open(QIODevice::Append);
写文件:file.write("哈哈哈哈哈");
关闭文件: file.close();
10.3 QFileInfo 文件信息读取
创建读取文件信息的对象:QFileInfo info(path);
可以读取大小size,后缀名suffix,文件名称fileName,文件路径path等
10.4 文件操作案例
#include "widget.h"
#include "ui_widget.h"
#include <QFileDialog>
#include <QFile>
#include <QTextCodec>
#include <QFileInfo>
#include <QDebug>
#include <QDateTime>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//点击选取文件按钮,弹出文件对话框
connect(ui->pushButton,&QPushButton::clicked,[=](){
QString path = QFileDialog::getOpenFileName(this,"打开文件","C:\\***\\***\\Desktop");
//将路径放入到lineEdit中
ui->lineEdit->setText(path);
//编码格式类
//QTextCodec *codec = QTextCodec::codecForName("gbk");
//读取内容,放入到textEdit中
//QFile默认支持的格式是utf-8
QFile file(path); //参数就是读取文件的路径
//设置打开方式
file.open(QIODevice::ReadOnly);
//全部读取
//QByteArray array = file.readAll();
//按行读
QByteArray array;
while( !file.atEnd()){
array += file.readLine();
}
//将读取到的数据,放入到textEdit中
ui->textEdit->setText(array);
//ui->textEdit->setText(codec->toUnicode(array));
//对文件对象进行关闭
file.close();
//进行写文件
//用追加方式进行写
file.open(QIODevice::Append);
file.write("哈哈哈哈哈");
file.close();
//QFileInfo 文件信息类
QFileInfo info(path);
qDebug()<<"大小:"<<info.size()<<" 后缀名:"<<info.suffix()<<" 文件名称:"<<info.fileName()<<" 文件路径:"<<info.path();
qDebug()<<"创建日期:"<<info.created().toString("yyyy/MM/dd hh:mm:ss");
qDebug()<<"最后修改日期:"<<info.lastModified().toString("yyyy/MM/dd hh:mm:ss");
});
}
Widget::~Widget()
{
delete ui;
}