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;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章