Bootstrap

Qt5相关知识

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;
}

;