黑马Qt_Day03

1、绘图事件

Qt 的绘图系统实际上是,使用QPainter在QPainterDevice上进行绘制,它们之间使用QPaintEngine进行通讯(也就是翻译QPainter的指令)。

mywidget.h

protected:
    //重写绘图事件,虚函数
    //如果在窗口绘图,必须放在绘图事件里实现
    //绘图事件内部自动调用,窗口重绘的时候(状态改变:窗口变大变小、鼠标点击焦点改变等)
    //允许认为调用
    void paintEvent(QPaintEvent *event) override;

mywidget.cpp

#include<QPainter>//画家
#include<QPen>//画笔
#include<QBrush>//画刷
#include<QPoint>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    x=0;//坐标
}

Widget::~Widget()
{
    delete ui;
}

//绘图事件
//绘图事件里面不要做太复杂的事件处理,耗时,因为该事件随时调用,自动调用
void Widget::paintEvent(QPaintEvent *event)
{
    //创建画家对象
    //方法一
    //QPainter p(this);

    //方法二
    QPainter p;
    p.begin(this);//指定当前窗口为绘图设备。。。后面一定要有p.end;

    //绘图操作
    //p.drawxxx();
    //画背景图
    //不生成资源的话要把图片文件夹的位置放在项目文件的同一级目录
    //p.drawPixmap(0,0,width(),height(),QPixmap("../image/1.jpg"));//指定背景图的坐标及大小:窗口的宽度、高度
    //p.drawPixmap(rect(),QPixmap("../image/1.jpg"));//等价于上一行代码,rect()获取矩形区域

    //定义画笔
    QPen pen;
    pen.setWidth(5);//设置线宽
    //pen.setColor(Qt::red);
    pen.setColor(QColor(128,255,255));//rgb设置颜色
    pen.setStyle(Qt::DashDotLine);//设置风格(虚直线?)

    //把画笔交给画家
    p.setPen(pen);


    //画直线
    p.drawLine(50,50,150,50);
    p.drawLine(50,50,50,150);

    QBrush brush;
    brush.setColor(Qt::white);
    brush.setStyle(Qt::Dense1Pattern);
    p.setBrush(brush);

    //画矩形
    p.drawRect(150,150,100,50);

    //画圆型
    p.drawEllipse(QPoint(150,150),50,25);

    //画上图片
    p.drawPixmap(x,180,80,80,QPixmap("../image/cute.jpg"));

    p.end();
}


void Widget::on_pushButton_clicked()
{
    x+=20;
    if(x>width())
    {
        x=0;
    }
    //刷新窗口,让窗口重绘,整个窗口都刷新
    update();//间接调用paintEvent(),update绝对不能放在paintEvent()里面,疯狂递归
}

2、QBitmap和QPixmap的区别:

QBitmap是QPixmap的子类

1)QPixmap,用于画彩色图片

2)QBitmap,用于只有黑白两种颜色,绘图事件中,若只要两种颜色建议用QBitmap,内存小一些,效率高,如光标文件和笔刷

#include<QPainter>
#include<QPixmap>
#include<QBitmap>


void Widget::paintEvent(QPaintEvent *e)
{
    //创建画家
    QPainter p(this);

    //图片背景透明
    //QPixmap
    p.drawPixmap(0,0,200,200,QPixmap("../image/cute2.png"));
    //QBitmap
    p.drawPixmap(200,0,200,200,QBitmap("../image/cute2.png"));

    //图片背景不透明
    //QPixmap
    QPixmap pixmap;
    pixmap.load("../image/cute.jpg");
    p.drawPixmap(0,200,200,200,pixmap);

    //QBitmap
    QBitmap bitmap;
    bitmap.load("../image/cute.jpg");
    p.drawPixmap(200,200,200,200,bitmap);
}

3、绘图设备

绘图设备是指继承QPainterDevice的子类

QPixmap:针对屏幕进行优化,和平台无关,不能对图片对图片进行修改

QImage:和平台有关,可以对图片进行修改(修改像素点如,颜色),在线程中绘图(如图像处理、视频、地图)

QPicture:保存绘图的状态(二进制文件),主要用于平台不相关,可以记录和重现QPainter的各条指令

 ①QPixmap

#include "widget.h"
#include "ui_widget.h"
#include<QPainter>

//不在窗口里面绘图,故不要求一定在paintEvent里实现
//现在指定的绘图设备为QPixmap,不是窗口,因此放在构造函数绘图就可以了
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //绘图设备,400*300
    QPixmap pixmap(400,300);

    //画家
    QPainter p(&pixmap);

    //填充白色背景色,不填充的话为黑色
    //p.fillRect(0,0,400,300,QBrush(Qt::white));
    pixmap.fill(Qt::white);//与上面等价

    p.drawPixmap(0,0,80,80,QPixmap("../image/cute2.png"));

    //画在设备上,非窗口,要把它保存成一张图片,不显示窗口,直接生成一张图片,名称与格式自己指定
    pixmap.save("../pixmap.jpg");
}

② QImage:操作与QPixmap差不多

#include "widget.h"
#include "ui_widget.h"
#include<QPainter>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //绘图设备
    //QImage::Format_ARGB32,透明背景色
    QImage image(600,600,QImage::Format_ARGB32);

    //画家
    QPainter p;
    p.begin(&image);
    //绘图可以是QPixmap、Image等
    p.drawImage(0,0,QImage("../image/cute2.png"));

    //操作像素点
    for(int i=0;i<50;i++)
    {
        for(int j=0;j<50;j++)
        {
            image.setPixel(i,j,qRgb(255,128,128));
            //获取像素点,暂时用不上
            //image.pixel(QPoint(i,j));
        }
    }
    p.end();

    //保存图片
    image.save("../image.png");
}

③QPicture:

#include "widget.h"
#include "ui_widget.h"
#include<QPicture>
#include<QPainter>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //绘图设备
    QPicture picture;

    //画家
    QPainter p;
    p.begin(&picture);

    //绘图
    p.drawPixmap(0,0,80,80,QPixmap("../image/cute2.png"));
    p.drawLine(50,50,150,50);

    p.end();

    //保存的是图片状态,二进制文件
    picture.save("../picture.png");

}

Widget::~Widget()
{
    delete ui;
}

//将图片状态加载到窗口
//在窗口上绘图,重写绘图事件
void Widget::paintEvent(QPaintEvent *event)
{
    QPicture pic;
    pic.load("../picture.png");//加载文件

    QPainter p(this);
    p.drawPicture(0,0,pic);
}

 ④QImage和QPixmap的相互转换:

QPicture,保存后加载就可以直接绘图;但是在实际运用中,QImage和QPixmap常常需要相互转换,QImage与平台无关,因此,传输过程用的是QImage;而实际绘画过程使用QPixmap,因为它对屏幕进行了优化

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter p(this);
    QPixmap pixmap;
    pixmap.load("../image/cute2.png");
    //QPixmap->QImage
    QImage tempImage=pixmap.toImage();
    p.drawImage(0,0,tempImage);

    QImage image;
    image.load("../image/cute2.png");
    //QImage->QPixmap
    QPixmap tempPix=QPixmap::fromImage(image);
    p.drawPixmap(400,0,tempPix);

}

4、不规则窗口

将图片换成透明背景的工具(若不会使用PS):https://www.gaoding.com/koutu

需求:将一张背景为透明的图片显示到窗口,且去除窗口的边框(也去除了关闭按钮等),实现右击鼠标关闭窗口,长按鼠标左键并移动实现拖拽窗口

widget.h

protected:
    void paintEvent(QPaintEvent *event) override;

    void mouseMoveEvent(QMouseEvent *e) override;
    void mousePressEvent(QMouseEvent *) override;


private:
    Ui::Widget *ui;

    QPoint p;

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QPainter>
#include<QMouseEvent>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //去窗口边框| windowFlags(),保留窗口特性的同时去除窗口边框
    setWindowFlags(Qt::FramelessWindowHint | windowFlags());

    //把窗口背景设置为透明
    setAttribute(Qt::WA_TranslucentBackground);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter p(this);
    p.drawPixmap(0,0,QPixmap("../image/乔巴_hyaline.png"));
}

//窗口去边框,没法关闭窗口和移动窗口,因此需要重写鼠标移动事件
void Widget::mouseMoveEvent(QMouseEvent *e)
{
    //移动,是buttons!!!
    if(e->buttons() & Qt::LeftButton)
    {

        this->move(e->globalPos()-p);
    }
}

void Widget::mousePressEvent(QMouseEvent *e)
{
    if(e->button()==Qt::RightButton)
    {
        //点击右键,关闭窗口
        close();
    }
    if(e->button()==Qt::LeftButton)
    {
        //求坐标差值
        //当前点击坐标-窗口左上角坐标
        p=e->globalPos() - this->frameGeometry().topLeft();//包括边框的窗口的左上角
        //this->geometry();//获取不包括边框的主工作区的矩形
    }

}

5、文件系统

  • QIODevice:所有 I/O 设备类的父类,提供了字节块读写的通用操作以及基本接口;
  • QFileDevice:Qt5新增加的类,提供了有关文件操作的通用实现;
  •  QFlie:访问本地文件或者嵌入资源;
  • QTemporaryFile:创建和访问本地文件系统的临时文件;
  • QBuffer:读写QbyteArray, 内存文件;
  • QProcess:运行外部程序,处理进程间通讯;
  • QAbstractSocket:所有套接字类的父类;
  • QTcpSocket:TCP协议网络数据传输;
  • QUdpSocket:传输 UDP 报文;

     

     

     

  • QSslSocket:使用 SSL/TLS 传输数据

 文件系统分类:

  顺序访问设备:

是指它们的数据只能访问一遍:从头走到尾,从第一个字节开始访问,直到最后一个字节,中途不能返回去读取上一个字节,这其中,QProcess、QTcpSocket、QUdpSoctet和QSslSocket是顺序访问设备。

  随机访问设备:

可以访问任意位置任意次数,还可以使用QIODevice::seek()函数来重新定位文件访问位置指针,QFile、QTemporaryFile和QBuffer是随机访问设备

1)字符编码转换

//打开文件
//QString path=QFileDialog::getOpenFileName(this,"open","../","TXT(*.txt)");//指定文件格式,也可以不指定(所有格式)
//保存文件
QString path=QFileDialog::getSaveFileName(this,"save","../","TXT(*.txt)");

//创建文件对象
QFile file;
file.setFileName(path);//QFile file(path);

//获取编辑区内容
QString str=ui->textEdit->toPlainText();
①QString -> QByteArray
 file.write(str.toUtf8());
②QString -> C++ string ->char*
 file.write(str.toStdString().data());
 
③转换成本地平台编码(Windows:ANSI)
 file.write(str.toLocal8Bit());
④QString -> QByteArray
  QString buf="123";
  QByteArray a=buf.toUtf8();//UTF8主要是针对有中文字符
  a=buf.toLocal8Bit();//本地编码,上下两种转换方式返回值都是QByteArray 

⑤QByteArray -> char*
   char * b=a.data();
⑥char * -> QString  网络编程会常常用到
    char *p="abc";
    QString c=QString(p);

2)QFile读写文件及获取文件信息

需求:通过readButton打开文件,将内容显示到文本框;通过writeButton将文本框内的内容存进文件

#include "widget.h"
#include "ui_widget.h"
#include<QFile>
#include<QFileDialog>
#include<QFileInfo>//获取文件信息
#include<QDebug>
#include<QDateTime>

void Widget::on_ButtonRead_clicked()
{
    //获取文件路径
    QString path=QFileDialog::getOpenFileName(this,
                             "open","../","TXT(*.txt)");//指定文件格式,也可以不指定(所有格式)
    if(path.isEmpty()==false)
    {
        //文件对象
        QFile file(path);

        //打开文件,只读方式
        bool isOk=file.open(QIODevice::ReadOnly);
        if(isOk==true)
        {
#if 0            //读文件,两种方法,默认只识别utf_8编码,要读取其他编码需借助文本流

            //1)一次读完,不靠谱,文件很大时
            QByteArray array=file.readAll();
            //显示到编辑区
            //ui->textEdit->setText(QString(array));
            ui->textEdit->setText(array);//会自动转换成QSreing,QString的构造函数有一种是字节数组转换的

#endif
            //2)一行行读取
            QByteArray array;
            while(file.atEnd()==false)
            {
                //读一行
                array+=file.readLine();

            }
            ui->textEdit->setText(array);

        }

        //关闭文件
        file.close();

        //获取文件信息
        QFileInfo info(path);
        qDebug()<<"文件名字:"<<info.fileName().toUtf8().data();//转成char*
        qDebug()<<"文件后缀:"<<info.suffix();
        qDebug()<<"文件大小:"<<info.size();//单位为字节,*1024=KB
        qDebug()<<"文创建时间:"<<info.birthTime().toString("yyyy-MM-dd hh:mm:ss");//2020-4-5 13:13:00

    }
}

void Widget::on_ButtonWrite_clicked()
{

    QString path=QFileDialog::getSaveFileName(this,"save","../","TXT(*.txt)");
    if(path.isEmpty()==false)
    {
        //创建文件对象
        QFile file;
        file.setFileName(path);

        //打开文件
        bool isOk=file.open(QIODevice::WriteOnly);
        if(isOk==true)
        {
            //获取编辑区内容
            QString str=ui->textEdit->toPlainText();

            //写文件
            //①QString -> QByteArray
            //file.write(str.toUtf8());

            //②QString -> C++ string ->char*
            //file.write(str.toStdString().data());

            //③转换成本地平台编码(Windows:ANSI)
            file.write(str.toLocal8Bit());

            //QString -> QByteArray
            QString buf="123";
            QByteArray a=buf.toUtf8();//UTF8主要是针对有中文字符
            a=buf.toLocal8Bit();//本地编码,上下两种转换方式返回值都是QByteArray

            //QByteArray -> char*
            char * b=a.data();

            //char * -> QString  网络编程会常常用到
            char *p="abc";
            QString c=QString(p);


        }

        file.close();
    }


}

3)QDataStream(二进制)

#include "widget.h"
#include "ui_widget.h"
#include<QDataStream>//数据流,以二进制方式操作,很灵活,文件,音频等都可以操作
#include<QFile>//打开文件、关联路径
#include<QDebug>
//__FILE__哪个文件输出打印;__LINE__文件代码的行号;C语言的全局宏
#define cout qDebug() << "[" << __FILE__ << ":" << __LINE__<<"]"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    writeData();
    readData();
}

Widget::~Widget()
{
    delete ui;
}

void Widget::writeData()
{
    //创建文件对象
    QFile file("../test.txt");

    //打开文件,只写
    bool isOk=file.open(QIODevice::WriteOnly);
    if(isOk==true)
    {
        //创建数据流,和file文件关联
        //往数据流中写数据,相当于往文件里写数据
        QDataStream stream(&file);

        stream<<QString("啦啦啦啦啦")<<250;
        file.close();
    }
}

void Widget::readData()
{
    //创建文件对象
    QFile file("../test.txt");

    //打开文件,只读
    bool isOk=file.open(QIODevice::ReadOnly);
    if(isOk==true)
    {
        //文件流
        //往文件流中读数据,相当于从文件里读数据
        QDataStream stream(&file);
        //读的时候,按写的顺序读取
        QString str;
        int a;
        stream>>str>>a;
        //qDebug()<<str.toUtf8().data()<<a;
        //qDebug()<<str<<a;
        cout<<str.toUtf8().data()<<a;
        file.close();

    }

}
//__FILE__哪个文件输出打印;__LINE__文件代码的行号;C语言的全局宏,好用
#define cout qDebug() << "[" << __FILE__ << ":" << __LINE__<<"]"
cout<<str.toUtf8().data()<<a;

 

4)QTextStream

#include "widget.h"
#include "ui_widget.h"
#include<QString>
#include<QFile>
#include<QTextStream>//文本流,读写时可指定编码
#include<QFileDialog>

#include<QDebug>
#define cout qDebug()<<"["<<__FILE__<<":"<<__LINE__<<"]"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    writeData();
    readData();
}

Widget::~Widget()
{
    delete ui;
}

void Widget::writeData()
{
    //创建文本对象
    QFile file;
    file.setFileName("../TextStream.txt");

    //打开文件,只写
    bool isOk=file.open(QIODevice::WriteOnly);
    if(true==isOk)
    {
        QTextStream stream(&file);

        //指定编码,不指定时生成编码与平台相关
        stream.setCodec("UTF-8");

        stream<<QString("啦啦啦啦啦")<<250;

        file.close();
    }
}

void Widget::readData()
{
    //创建文件对象
    QFile file("../TextStream.txt");

    bool isOk=file.open(QIODevice::ReadOnly);

    //读文件不推荐,有bug
//    if(true==isOk)
//    {
//        QTextStream stream(&file);
//        //指定编码
//        stream.setCodec("UTF-8");//与所读文件编码匹配
//        QString str;
//        int a;

//        //读取时把“啦啦啦啦啦250”赋值给str,中间没空格,a没有内容故赋值为0
//        stream>>str>>a;
//        cout<<str.toUtf8().data()<<a;

//        file.close();
//    }
}

void Widget::on_pushButton_clicked()
{
    QString path=QFileDialog::getOpenFileName(this,"open","../");
    if(false==path.isEmpty())
    {
        QFile file;
        file.setFileName(path);

        bool isOk=file.open(QIODevice::ReadOnly);
        if(true==isOk)
        {
            QTextStream stream(&file);
            //指定编码
            stream.setCodec("UTF-8");

            QString str=stream.readAll();
            ui->textEdit->setText(str);
            file.close();
        }
    }
}
void Widget::readData()运行结果:

 5)QBuffer(内存文件)

#include "widget.h"
#include "ui_widget.h"
#include<QBuffer>//内存文件
#include<QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //QBuffer memFile;//创建内存文件
    QByteArray array;
    QBuffer memFile(&array);//指定内存数组,将数据放入
    memFile.open(QIODevice::WriteOnly);

    memFile.write("1111111111111111");
    memFile.write("22222222222222222222222222");

    memFile.close();

    qDebug()<<memFile.buffer();
    qDebug()<<"array"<<array;

      QBuffer memFile1;
      memFile1.open(QIODevice::WriteOnly);
      QDataStream stream(&memFile1);
      stream<<QString("测试")<<250;
      memFile1.close();

//    qDebug()<<memFile1.buffer();//转换麻烦,且内容整在一起

    memFile1.open(QIODevice::ReadOnly);
    QDataStream in;
    in.setDevice(&memFile1);//缓冲区内容也是二进制的
    QString str;
    int a;
    in>>str>>a;
    memFile1.close();
    qDebug()<<str.toUtf8().data()<<a;

}

Widget::~Widget()
{
    delete ui;
}

 
 



猜你喜欢

转载自www.cnblogs.com/lalala-lueluelue/p/12629428.html