企业网站建设太原网站建设,建设网站需要购买哪些,怎么做云购网站,部门网站管理建设工作汇报QT的绘图系统#xff08;QPainterDevice#xff09;与文件系统#xff08;QIODevice#xff09; 文章目录 1、Qt 的绘图系统1、QPainter的使用2、QPen(画笔#xff09;及QBursh#xff08;画刷#xff09;3、手动更新窗口4、绘图设备1、四种绘图设备的 区别2、 QBitmap3…QT的绘图系统QPainterDevice与文件系统QIODevice 文章目录 1、Qt 的绘图系统1、QPainter的使用2、QPen(画笔及QBursh画刷3、手动更新窗口4、绘图设备1、四种绘图设备的 区别2、 QBitmap3、QPixmap4、 QImage5、QPicture6、QImage与QPixmap的转换 2、不规则窗口3、文件系统1、QFile文件的读写2、QT的QString与QByteArray以及char *的相互转换3、文件信息QFileInfo类4、二进制文件读写 QDataStream类(打开是看不懂5、文本文件读写QTextStream类6、内存读写QBuffer类 4、总结 1、Qt 的绘图系统
Qt 的绘图系统允许使用相同的 API 在屏幕和其它打印设备上进行绘制。整个绘图系统基于QPainterQPainterDevice和QPaintEngine三个类。 下图给出了这三个类之间的层次结构: 上面的示意图告诉我们Qt 的绘图系统实际上是使用QPainter在QPainterDevice上进行绘制它们之间使用QPaintEngine进行通讯也就是翻译QPainter的指令。
1、QPainter的使用
对窗口绘图首先要重写**void paintEvent(QPaintEvent *)**虚函数。
重写绘图事件虚函数如果在窗口绘图必须放在绘图事件里实现绘图事件内部自动调用窗口需要重绘的时候状态改变
void MyWidget::paintEvent(QPaintEvent *)
{QPainter p(this);//指定当前窗口为绘图设备p.drawPixmap(rect(), QPixmap(../Image/bk.jpg)); //画背景图//画直线p.drawLine(50, 50, 150, 50); /* 在坐标50,50的位置画长150宽50的线 */p.drawLine(50, 50, 50, 150);//画矩形;l;dp.drawRect(150, 150, 100, 50);//画圆形p.drawEllipse(QPoint(150, 150), 50, 25);
}注意在上层目录要有背景图的存在。要先画背景图在画直线矩形圆形。 指定QQidget对象为绘图对象。即窗口是绘图设备。QQidget继承与QPaintDevice.
2、QPen(画笔及QBursh画刷
QPainter有很多以 draw 开头的函数用于各种图形的绘制比如drawLine()drawRect()以及drawEllipse()等。 如果需要设置画家的颜色风格线条的粗细。从而引入画笔。如果需要填充图形的颜色需要画刷。
void MyWidget::paintEvent(QPaintEvent *)
{QPainter p(this);//指定当前窗口为绘图设备//画背景图p.drawPixmap(rect(), QPixmap(../Image/bk.jpg));//定义画笔QPen pen;pen.setWidth(5); //设置线宽pen.setColor( QColor(14, 9, 234) );//rgb设置颜色pen.setStyle(Qt::DashLine); //设置风格p.setPen(pen); //把画笔交给画家QBrush brush; //创建画刷对象brush.setColor(Qt::red); //设置颜色brush.setStyle(Qt::Dense1Pattern);//设置样式p.setBrush(brush);//把画刷交给画家//画直线p.drawLine(50, 50, 150, 50); /* 在坐标50,50的位置画长150宽50的线 */p.drawLine(50, 50, 50, 150);//画矩形;l;dp.drawRect(200, 200, 100, 50);//画圆形p.drawEllipse(QPoint(150, 150), 50, 25);
}3、手动更新窗口
当我们在窗口绘制的图不断变化时。需要不断地刷新窗口才会有变化。否则不会有。 mywidget.h
class MyWidget : public QWidget
{Q_OBJECT
public:MyWidget(QWidget *parent nullptr);~MyWidget();void paintEvent(QPaintEvent *);
private:int x;QPushButton *button;
private slots:void FunSlot(void);
private:Ui::MyWidget *ui;
};mywidget.cpp
#include mywidget.h
#include ui_mywidget.h
#include QPainterMyWidget::MyWidget(QWidget *parent) :QWidget(parent),ui(new Ui::MyWidget)
{ui-setupUi(this);x 0;QPushButton *button new QPushButton(this);button-setText(向右移动);connect(button, QPushButton::pressed, this, MyWidget::FunSlot);
}MyWidget::~MyWidget()
{delete ui;
}void MyWidget::paintEvent(QPaintEvent *)
{QPainter p(this);//画笑脸p.drawPixmap(x, 180, 80, 80, QPixmap(../Image/face.png));}
void MyWidget::FunSlot(void)
{x 20;if(x width()- 80){x 0;}//刷新窗口让窗口重绘整个窗口都刷新update(); //间接调用paintEvent()
}
点击按钮绘图不断向右移动变化。到窗口终点又回到起点。
4、绘图设备
1、四种绘图设备的 区别
绘图设备是指继承QPainterDevice的子类。Qt一共提供了四个这样的类分别是QPixmap、QBitmap、QImage和 QPicture。 **QBitmap**是QPixmap的一个子类它的色深限定为1可以使用 QPixmap的isQBitmap()函数来确定这个QPixmap是不是一个QBitmap。 总结它们操作都方法都是差不多一样的。
2、 QBitmap
QBitmap只有黑白两种颜色。
void MyWidget::paintEvent(QPaintEvent *)
{QPainter p(this);//QPixmap 图片背景透明p.drawPixmap(0, 0, QPixmap(../Image/face.png));//QBitmap 图片背景透明p.drawPixmap(200, 0, QBitmap(../Image/face.png));//QPixmap 图片背景白色QPixmap pixmap;pixmap.load(../Image/image.jpg);p.drawPixmap(0, 200, pixmap);//QBitmap 图片背景白色QBitmap bitmap;bitmap.load(../Image/image.jpg);p.drawPixmap(400, 200, bitmap);
}右边为QBitmap 左边为QPixmap。上面的QBitmap为黑色背景。下面为QBitmap的白色背景。
3、QPixmap
如下在QPixmap绘图而不是在窗口。不用重写绘图事件。在构造函数里实现即可。
MyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget)
{ui-setupUi(this);//绘图设备 400*300QPixmap 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/face.png));//上层路径保存图片pixmap.save(../pixmap.jpg);
}在上层目录生成pixmap.jpg文件。
4、 QImage
QImage可以对像素点进行操作。
Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui-setupUi(this);//创建一个绘图设备QImage::Format_ARGB32背景是透明QImage image(400, 300, QImage::Format_ARGB32);QPainter p;p.begin(image);//绘图p.drawImage(0, 0, QImage(../Image/image.jpg));//对绘图设备前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.pixel(QPoint(i, j)); /* 获取像素点 */}}p.end();image.save(../image.png); // 保存图片
}在上层目录生成image.png文件。绿色部分为对像素点的操作。
5、QPicture
MyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget)
{ui-setupUi(this);QPicture picture;QPainter p;p.begin(picture);p.drawPixmap(0, 0, 80, 80, QPixmap(../Image/face.png));p.drawLine(50, 50, 150, 50);p.end();//保存的是二进制文件picture.save(../picture.png);
}在上层路径生成picture.png的二进制文件。 二进制打开也看不出效果。我们在窗口里加载出来。重写绘图事件。
void MyWidget::paintEvent(QPaintEvent *)
{QPicture pic;pic.load(../picture.png); //加载二进制picture.png文件QPainter p(this);p.drawPicture(0, 0, pic);
}运行结果如下
6、QImage与QPixmap的转换
在对屏幕进行优化可能需要用到QPixmap。在传输可能需要用到QImage。
void MyWidget::paintEvent(QPaintEvent *)
{QPainter p(this);QPixmap pixmap;pixmap.load(../Image/face.png);//QPixmap - QImageQImage tempImage pixmap.toImage();p.drawImage(0, 0, tempImage);QImage image;image.load(../Image/face.png);//QImage - QPixmapQPixmap tempPixmap QPixmap::fromImage(image);p.drawPixmap(200, 0, tempPixmap);
}运行结果 第一张是通过QPixmap转QImage画的。第二张是通过QImage转QPixmap画的。
2、不规则窗口
常见的窗体是各种方形的对话框,但有时候也需要非方形的窗体,如圆形,椭圆甚至是不规则形状的对话框。 widget.h
class Widget : public QWidget
{Q_OBJECT
public:explicit Widget(QWidget *parent 0);~Widget();protected:void paintEvent(QPaintEvent *);void mouseMoveEvent(QMouseEvent *e);void mousePressEvent(QMouseEvent *e);
private:QPoint p;
private:Ui::Widget *ui;
};widget.cpp
#include widget.h
#include ui_widget.h
#include QPainter
#include QMouseEventWidget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui-setupUi(this);//去窗口表框Qt::FramelessWindowHint windowFlags()其它属性不变setWindowFlags(Qt::FramelessWindowHint | windowFlags());//把窗口背景设置为透明setAttribute(Qt::WA_TranslucentBackground);
}Widget::~Widget()
{delete ui;
}void Widget::paintEvent(QPaintEvent *)
{QPainter p(this);p.drawPixmap(0, 0, QPixmap(../Image/sunny.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() - p); // 当前点击坐标(屏幕 - 求坐标差值}
}当鼠标左键按下移动无规则窗口跟着移动。鼠标右键按下则无规则窗口关闭。 如下图片关于上面代码的坐标计算的示意图
3、文件系统
文件操作是应用程序必不可少的部分。Qt 作为一个通用开发库提供了跨平台的文件操作能力。Qt 通过QIODevice提供了对 I/O 设备的抽象这些设备具有读写字节块的能力。下面是 I/O 设备的类图Qt5
1、QFile文件的读写
QFile提供了从文件中读取和写入数据的能力。 我们通常会将文件路径作为参数传给QFile的构造函数。不过也可以在创建好对象最后使用setFileName()来修改。 ui界面如下 功能把读取到文件显示在文本框里。把文本框里的内容保存成文件。
#include mywidget.h
#include ui_mywidget.h
#includeQFile
#includeQFileDialog
#includeQDebugMyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget)
{ui-setupUi(this);connect(ui-pushButtonRead, QPushButton::pressed, this, MyWidget::ReadSlot);connect(ui-pushButtonWrite, QPushButton::pressed, this, MyWidget::WriteSlot);
}MyWidget::~MyWidget()
{delete ui;
}void MyWidget::ReadSlot(void)
{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));//ui-textEdit-setText(array);
#endif// 一次读取一行QByteArray array;while( file.atEnd() false){//读一行array file.readLine();}ui-textEdit-setText(array);}//关闭文件file.close();}
}void MyWidget::WriteSlot(void)
{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();//写文件file.write(str.toUtf8());}file.close();}
}2、QT的QString与QByteArray以及char *的相互转换 // QString - QByteArrayfile.write(str.toUtf8());//QString - c string - char *file.write(str.toStdString().data());//转换为本地平台编码file.write(str.toLocal8Bit());//QString - QByteArrayQString buf 123;QByteArray a buf.toUtf8(); //中文a buf.toLocal8Bit(); //本地编码//QByteArray - char *char *b a.data();//char * - QStringchar *p abc;QString c QString(p);3、文件信息QFileInfo类 #include QFileDialog
#include QFileInfo
#include QDebug
#include QDateTimeQString path QFileDialog::getOpenFileName(this, open, ../);if(path.isEmpty() false){//获取文件信息QFileInfo info(path);qDebug() 文件名字 info.fileName().toUtf8().data();qDebug() 文件后缀 info.suffix();qDebug() 文件大小 info.size();qDebug() 文件创建时间 info.birthTime().toString(yyyy-MM-dd hh:mm:ss); //2024-01-04 15:13:00}4、二进制文件读写 QDataStream类(打开是看不懂 mywidget.h
#include QWidget
QT_BEGIN_NAMESPACE
namespace Ui { class MyWidget; }
QT_END_NAMESPACEclass MyWidget : public QWidget
{Q_OBJECTpublic:MyWidget(QWidget *parent nullptr);~MyWidget();void writeData();void readData();
private:Ui::MyWidget *ui;
};mywidget.cpp
#include mywidget.h
#include ui_mywidget.h
#include QDataStream
#include QFile
#include QDebug
#define cout qDebug() [ __FILE__ : __LINE__ ]MyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget)
{ui-setupUi(this);writeData();readData();
}MyWidget::~MyWidget()
{delete ui;
}void MyWidget::writeData()
{//创建文件对象QFile file(../hello.txt);//打开文件 只写方式打开bool isOk file.open(QIODevice::WriteOnly);if(true isOk){//创建数据流和file文件关联//往数据流中写数据相当于往文件里写数据QDataStream stream(file);stream QString(你好) 777;file.close();}}void MyWidget::readData()
{//创建文件对象QFile file(../hello.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();}
}先写入数据流二进制形式然后以写的顺序读出来。 需要注意的是你必须按照写入的顺序将数据读取出来。顺序颠倒的话程序行为是不确定的严重时会直接造成程序崩溃。 那么既然QIODevice提供了read()、readLine()之类的函数为什么还要有QDataStream呢QDataStream同QIODevice有什么区别区别在于QDataStream提供流的形式性能上一般比直接调用原始 API 更好一些。
5、文本文件读写QTextStream类 ui界面
widget.h
#include QWidgetnamespace Ui {
class Widget;
}
class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent 0);~Widget();void writeData();
private slots:void on_pushButton_clicked();
private:Ui::Widget *ui;
};widget.cpp
#include widget.h
#include ui_widget.h
#include QTextStream
#include QFile
#include QDebug
#include QFileDialog
#define cout qDebug() [ __FILE__ : __LINE__ ]Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui-setupUi(this);writeData();}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.setEncoding(QStringConverter::Utf8);stream QString(你好) 777;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.setEncoding(QStringConverter::Utf8);QString str stream.readAll();ui-textEdit-setText(str);file.close();}}
}当使用QDataStream写入的时候实际上会在要写入的内容前面额外添加一个这段内容的长度值。而以文本形式写入数据是没有数据之间的分隔的。因此使用文本文件时很少会将其分割开来读取而是使用诸如使用: QTextStream::readLine() 读取一行 QTextStream::readAll()读取所有文本。
6、内存读写QBuffer类 QByteArray array;QBuffer memFile(array); //创建内存文件 还指定QByteArray对象memFile.open(QIODevice::WriteOnly);memFile.write(5455454);memFile.write(6564565);memFile.close();qDebug() memFile.buffer();qDebug() array: array;写进了内存也保存在了指定的QByteArray对象里。
QBuffer与QDataStream一起操作dome。 QBuffer memFile1;memFile1.open(QIODevice::WriteOnly); /* 只写 */QDataStream stream(memFile1); /* QBuffer与QDataStream关联 */stream QString(测试) 999;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;qDebug() memFile1.buffer();运行结果
4、总结
例如以上就是今天要讲的内容本文仅仅简单介绍了QT的绘图系统与文件系统。