Qt学习第3天:绘图(绘图设备)和文件系统 【笔记】

小技巧:
.->没提示的时候,一般是没包含头文件
② 函数查看帮助时,没有参数打不开帮助文档,在参数列表填写0x0,按F1即可实现函数对应的文档查看。

1. 绘图

注意,更新窗口时update不能放在事件函数paintEvent中,否则会死循环
绘图操作中不能有太复杂的运算,否则会很卡

背景图绘制、简单绘图及手动更新窗口

在这里插入图片描述
widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

protected:
    //重写绘图事件,虚函数
    //如果在窗口绘图,必须放在绘图事件里实现
    //绘图事件内部自动调用,窗口需要重绘的时候(状态改变)
    void paintEvent(QPaintEvent *);

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;

    int x;
};

#endif // WIDGET_H

widget.cpp

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

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

    x = 0;

}

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

void Widget::paintEvent(QPaintEvent *)
{
    //方式1:
    //QPainter p(this);

    //方式2:
    QPainter p; //创建画家对象
    p.begin(this);//指定当前窗口为绘图设备

    //绘图操作,code
    //p.drawxxxx();
    //画背景图
    //    方法1:
    //p.drawPixmap(0,0,width(),height(),QPixmap("://Image/background.jpg"));
    //    方法2:
    p.drawPixmap(rect(),QPixmap("://Image/background.jpg"));

    //定义画笔
    QPen pen;
    pen.setWidth(5);//设置线宽
    //pen.setColor(Qt::red);//设置颜色
    pen.setColor(QColor(14,9,234));//RGB颜色设置
    pen.setStyle(Qt::DashLine);

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


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

    //创建画刷对象
    QBrush brush;
    brush.setColor(Qt::red);//设置颜色
    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/11.png"));
    p.end();

}

void Widget::on_pushButton_clicked()
{
    x += 20;
    if(x > width())
    {
        x = 0;
    }

    //刷新窗口,让窗口重绘
    update();//间接调用paintEvent
}

QBitmap与QPixmap的区别

① QBitmap只有两种颜色:黑白
② QPixmap可画彩色图片
在这里插入图片描述
widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

protected:
    //重写绘图事件
    //如果给窗口绘图,一定要在paintEvent()绘制
    void paintEvent(QPaintEvent *);
private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

widget.cpp

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

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

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

void Widget::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    //QPixmap 图片背景透明
    p.drawPixmap(0,0,QPixmap("://11.png"));
    //QBitmap 图片背景透明
    p.drawPixmap(200,0,QBitmap("://11.png"));

    //QPixmap 图片背景白色
    QPixmap pixmap;
    pixmap.load("://11.png");
    p.drawPixmap(0,220,pixmap);

    //QBitmap 图片背景白色
    QBitmap bitmap;
    bitmap.load("://11.png");
    p.drawPixmap(200,220,bitmap);
}

绘图设备

  1. QPixmap:最常用,针对屏幕进行优化了,和平台相关,不能对图片进行修改
    widget.cpp
    #include "widget.h"
    #include "ui_widget.h"
    #include <QPainter>
    
    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
        //绘图设备,400*300
        QPixmap pixmap(400,300);
    
        QPainter p(&pixmap);
    
        //填充背景为白色
        //法1:通过画家填充
        //p.fillRect(0,0,400,300,QBrush(Qt::white));
        //法2:通过绘图设备填充
        pixmap.fill(Qt::white);
    
        p.drawPixmap(0,0,80,80,QPixmap(":/new/prefix1/11.png"));
    
        //保存图片
        pixmap.save("../pixmap.png");
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    

在这里插入图片描述
在这里插入图片描述

  1. QImage:和平台无关,可以对图片进行修改,可在线程中绘图
    widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QRgb>
#include <QImage>

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

    //创建一个绘图设备,背景透明
    QImage image(400,300,QImage::Format_ARGB32);
    QPainter p;
    p.begin(&image);

    //绘图
    p.drawImage(0,0,QImage("../11.png"));//项目上一层路径下

    //对绘图设备前50个像素点进行操作,一般不会这么用
    for(int i= 0;i < 50; i++)
    {
        for(int j=0;j<50;j++)
        {
            image.setPixel(QPoint(i,j), qRgb(0,255,0));
        }
    }


    //注意,保存的时候是绘图设备保存
    image.save("image.png");//注意,该路径是在项目build文件下
    p.end();
}

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

在这里插入图片描述

  1. QPicture:保存绘图的状态(二进制文件)

注意:保存的是二进制文件,是图片的一种状态!

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();
protected:
    void paintEvent(QPaintEvent *);
private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

widget.cpp

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

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("../11.png"));
    p.drawLine(50,50,150,50);

    p.end();

    //注意:保存的是二进制文件
    picture.save("picture.png");
}

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

void Widget::paintEvent(QPaintEvent *)
{
    QPicture pic;
    pic.load("picture.png");//加载二进制文件

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. QImage和QPixmap相互转换
protected:
    void paintEvent(QPaintEvent *);

widget.cpp

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

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("../11.png"));
    p.drawLine(50,50,150,50);

    p.end();

    //注意:保存的是二进制文件
    picture.save("picture.png");
}

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

void Widget::paintEvent(QPaintEvent *)
{
#if 0
    QPicture pic;
    pic.load("picture.png");//加载二进制文件

    QPainter p(this);
    p.drawPicture(0,0,pic);
#endif

    QPainter p(this);
    QPixmap pixmap;
    pixmap.load("../11.png");

    //QPixmap -> QImage
    QImage tempImage = pixmap.toImage();
    p.drawImage(0,0,tempImage);

    QImage image;
    image.load("../11.png");

    //QImage -> QPixmap
    QPixmap tempPixmap = QPixmap::fromImage(image);
    p.drawPixmap(200,0,tempPixmap);
}

在这里插入图片描述

2. 不规则窗口

设置窗口为无边框图形
widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();
protected:
    void paintEvent(QPaintEvent *);

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

widget.cpp

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

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

    //去窗口边框
    setWindowFlags(Qt::FramelessWindowHint | windowFlags());

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

}

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

void Widget::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    p.drawPixmap(0,0,QPixmap("../11.png"));
}

鼠标移动不了,接下来写鼠标移动事件:

注意,移动的是窗口的左上角
widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();
protected:
    void paintEvent(QPaintEvent *);
    void mouseMoveEvent(QMouseEvent *e);
    void mousePressEvent(QMouseEvent *e);

private:
    Ui::Widget *ui;
    QPoint p;
};

#endif // WIDGET_H

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

    //去窗口边框
    setWindowFlags(Qt::FramelessWindowHint | windowFlags());

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

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

void Widget::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    p.drawPixmap(0,0,QPixmap("../11.png"));
}

void Widget::mousePressEvent(QMouseEvent *e)
{
    if(e->button() == Qt::RightButton)
    {
        //如果是右键
        close();
    }
    else if (e->button() == Qt::LeftButton)
    {
        //求座标差值
        //当前点击座标-窗口左上角座标
        p = e->globalPos() - this->frameGeometry().topLeft();

    }
}

void Widget::mouseMoveEvent(QMouseEvent *e)
{
    if(e->buttons() & Qt::LeftButton)
    {
        //move(e->globalPos());//注意,如果这么写,移动的时候有个偏距
        move(e->globalPos() - p);
    }
}

在这里插入图片描述

3.文件读写

在这里插入图片描述

  • QBuffer
  • QProcess
  • QFileDevice
  • QAbstractSocket

读文件

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QFile>
#include <QFileDialog>

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

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

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
            //一次读完
            //读文件,默认只识别utf8编码
            QByteArray array = file.readAll();
            //显示到编辑区
            ui->textEdit->setText(QString(array));
#endif
            QByteArray array;//Qt的数据处理中,字节数组用的非常多
            while(file.atEnd() == false)
            {
                //读一行
                array += file.readLine();
            }
            ui->textEdit->setText(array);
        }
        //关闭文件
        file.close();
    }
}

写文件

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();
            //写文件
            //方法1:
            //file.write(str.toUtf8());

            //方法2:
            //Qstring -> c++ string -> char *
            //file.write(str.toStdString().data());

            //转换成本地平台编码
            file.write(str.toLocal8Bit());
        }
        //关闭文件
        file.close();
    }
}

在这里插入图片描述
在这里插入图片描述

QString、QByteArray、char *的相互转换

//QString -> QByteArray
QString buf = "123";
QByteArray a = buf.toUtf8();//中文
a = buf.toLocal8Bit();//本地编码
            
//QString -> QByteArray
QString buf = "123";
QByteArray a = buf.toUtf8();//中文
a = buf.toLocal8Bit();//本地编码

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

//char * -> QString
char *p = "abc";
QString c = QString(p);

QFileInfo获取文件信息

 QString path = QFileDialog::getOpenFileName(this,
                                                "open","../","TXT(*.txt)");
                                                
//获取文件信息
QFileInfo info(path);
qDebug() << "文件名称:" << info.fileName().toUtf8().data();
qDebug() << "文件后缀:" << info.suffix();
qDebug() << "文件大小:" << info.size();//单位字节
qDebug() << "文件创建时间:"<<info.created().toString("yyyy-MM-dd hh:mm:ss");

QDataStream读写文件

通过二进制读写文件

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

    //打开文件,以只写方式打开
    bool isOk = file.open(QIODevice::WriteOnly);
    if(true == isOk)
    {
        //创建数据流,和file文件关联
        //往数据流中输入数据,相当于往文件里写数据
        QDataStream stream(&file);
        //如果不转码,它会以二进制内容输出
        //stream << QString("主要看气质").toLocal8Bit()<<250;
        stream << QString("主要看气质")<<250;
        file.close();
    }
}

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

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


    }
    file.close();
}

QTextStream操作文件

通过文本方式操作,可以指定读写编码

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QTextStream>
#include <QFile>
#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("../demo.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;
    file.setFileName("../demo.txt");

    bool isOk = file.open(QIODevice::ReadOnly);
    if(true == isOk)
    {
        QTextStream stream(&file);
        //指定编码
        stream.setCodec("UTF-8");
        QString str;
        int a;
//        stream >> str >> a;
//        cout << str.toUtf8().data() << a;
        /*
         * 以上这种方式,调试结果如下:
         * [ ..\03day_10_QTextStream\widget.cpp : 54 ] 主要看气质250 0
         * 发现,末尾多了一个0
         */

        str = stream.readAll();
        cout <<str;

        file.close();
    }
}

QBuffer

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QBuffer>//内存文件
#include <QDebug>
#include <QDataStream>

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

    QByteArray array;
    QBuffer memFile(&array);//创建内存文件
    memFile.open(QIODevice::WriteOnly);
    memFile.write("1111");
    memFile.write("2222");
    memFile.write("3333");
    memFile.close();
    qDebug() << memFile.buffer();//输出时,三个字符串会连在一起,"111122223333"
    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;
}

小技巧

//方便调试用,输出文件名称和打印行号
#define cout qDebug() << "[" << __FILE__ <<":"<<__LINE__ <<"]"

//qDebug() << str.toUtf8().data() << a;
cout << str.toUtf8().data() << a;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章