界面编程之QT绘图和绘图设备20180728
/*******************************************************************************************/
一、绘图
整个绘图系统基于QPainter,QPainterDevice和QPaintEngine三个类:
QPainter(画家)->QPaintEngine(中间引擎,画家与设备之间的交互(通信接口),对于应用开发一般用不上)->QpaintDevice(设备,表示画在哪里)
画图的时候就是要重写事件:
protected:
//重写绘图事件,虚函数
//如果在窗口上(给窗口)绘图,必须放在绘图事件里实现
//绘图事件内部自动调用,窗口需要重绘的时候(窗口状态改变的时候)自动调用
//当然也可以人为的调用
void paintEvent(QPaintEvent *);
void Widget::paintEvent(QPaintEvent *)
{
//QPainter p(this);//这是一种方法,因为this是Widget也是一种绘图设备
//另一种方法,begin
QPainter p;//创建画家对象
p.begin(this);//指定当前窗口为绘图设备,因为this是Widget也是一种绘图设备
//绘图操作
//p.drawxxx();
//比如,画背景图(一般先画):
//p.drawPixmap(0, 0, width(), height(), QPixmap("../Image/bk.png")); //绘图操作
p.drawPixmap(rect(), QPixmap("../Image/bk.png"));
//定义画笔,画笔确定画家画出什么样的效果
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/face.png"));
//另一种方法,end
p.end();
/*******************************************************************************************/
二、手动更新窗口
调用update()函数:
void Widget::on_pushButton_clicked()
{
x += 20;
if(x > width())
{
x = 0;
}
//刷新窗口,让窗口重绘,没有参数所以整个窗口都刷新(重绘),如果有填入指定区域的参数,则只刷新区域部分
update(); //相当于间接调用paintEvent()
}
上述代码具体见《PaintEvent》
#ifndef WIDGET_H
#define WIDGET_H #include <QWidget> namespace Ui {
class Widget;
} class Widget : public QWidget
{
Q_OBJECT public:
explicit Widget(QWidget *parent = );
~Widget(); protected:
//重写绘图事件,虚函数
//如果在窗口绘图,必须放在绘图事件里实现
//绘图事件内部自动调用,窗口需要重绘的时候(状态改变)
void paintEvent(QPaintEvent *); private slots:
void on_pushButton_clicked(); private:
Ui::Widget *ui;
int x;
}; #endif // WIDGET_H
widget.h
#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 = ;
} Widget::~Widget()
{
delete ui;
} void Widget::paintEvent(QPaintEvent *)
{
//QPainter p(this); QPainter p;//创建画家对象
p.begin(this);//指定当前窗口为绘图设备 //绘图操作
//p.drawxxx();
//画背景图
//p.drawPixmap(0, 0, width(), height(), QPixmap("../Image/bk.png"));
p.drawPixmap(rect(), QPixmap("../Image/bk.png")); //定义画笔
QPen pen;
pen.setWidth(); //设置线宽
//pen.setColor(Qt::red); //设置颜色
pen.setColor( QColor(, , ) );//rgb设置颜色
pen.setStyle(Qt::DashLine); //设置风格 //把画笔交给画家
p.setPen(pen); //画直线
p.drawLine(, , , );
p.drawLine(, , , ); //创建画刷对象
QBrush brush;
brush.setColor(Qt::red); //设置颜色
brush.setStyle(Qt::Dense1Pattern);//设置样式 //把画刷交给画家
p.setBrush(brush); //画矩形
p.drawRect(, , , ); //画圆形
p.drawEllipse(QPoint(, ), , ); //画笑脸
p.drawPixmap(x, , , , QPixmap("../Image/face.png")); p.end();
} void Widget::on_pushButton_clicked()
{
x += ;
if(x > width())
{
x = ;
} //刷新窗口,让窗口重绘,整个窗口都刷新
update(); //间接调用paintEvent()
}
widget.cpp
/*******************************************************************************************/
三、QBitMap和QPixmap的区别
QBitMap是QPixmap的子类
QBitMap是黑白的图片
QPixmap是彩色的图片
#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("../Image/butterfly.png"));
//QBitmap 图片背景透明 透明的部分变为黑色了
p.drawPixmap(200, 0, QBitmap("../Image/butterfly.png"));
//QPixmap 图片背景白色
QPixmap pixmap;
pixmap.load("../Image/butterfly1.png");
p.drawPixmap(0, 200, pixmap);
//QBitmap 图片背景白色,白色变为透明了
QBitmap bitmap;
bitmap.load("../Image/butterfly1.png");
p.drawPixmap(200, 200, bitmap);
}
/*******************************************************************************************/
四、绘图设备
绘图设备主要有三种:
I、QPixmap //最常用,针对屏幕进行优化了,和平台(显卡)相关,不可以对图片进行修改 //QBitMap是QPixmap的子类 QBitMap是黑白的图片
II、QImage //没有优化,和平台无关,有自己的一套系统。可以对图片进行修改(像素点的修改),可以在线程中绘图即可以在单独开的线程中使用
III、QPicture //平台无关的,保存绘图的状态(保存为一个二进制文件),可以给另外的程序(平台)使用导致另外的绘的一样。
都可以在窗口上面绘图
1.QPixmap绘图设备
//绘图设备, 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/face.png"));
//把绘图设备中的图片(绘画结果)保存出来,保存图片
pixmap.save("../pixmap.jpg");
2.QImage绘图设备
//创建一个绘图设备,QImage::Format_ARGB32背景是透明
QImage image(400, 300, QImage::Format_ARGB32);
QPainter p;
p.begin(&image);
//绘图
p.drawImage(0, 0, QImage("../Image/face.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.pixel(QPoint(i, j));
}
}
p.end();
image.save("../image.png");
3.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("../Image/face.png"));
p.drawLine(50, 50, 150, 50);
p.end();
//保存的是二进制文件
picture.save("../picture.png");//把绘图状态(绘图操作)保存为二进制文件
}
void Widget::paintEvent(QPaintEvent *)
{
QPicture pic;
//加载文件
pic.load("../picture.png"); //加载之前绘图的操作,用于生成图片
QPainter p(this);
p.drawPicture(0, 0, pic);
}
4.QImage和QPixmap相互转换
QPixmap使用底层平台的绘制系统进行绘制,无法提供像素级别的操作,而QImage则是使用独立于硬件的绘制系统,实际上是自己绘制自己,
因此提供了像素级别的操作,并且能够在不同系统之上提供一个一致的显示形式。
比如网络传输的是QImage(因为和和平台无关),但是画的时候需要有优化的QPixmap,这时就需要吧接收到的
QImage转换为QPixmap
void Widget::paintEvent(QPaintEvent *)
{
QPainter p(this);
QPixmap pixmap;
pixmap.load("../Image/face.png");
//QPixmap -> QImage
QImage tempImage = pixmap.toImage();
p.drawImage(0, 0, tempImage);
QImage image;
image.load("../Image/face.png");
//QImage -> QPixmap
QPixmap tempPixmap = QPixmap::fromImage(image);
p.drawPixmap(100, 0, tempPixmap);
}
/*******************************************************************************************/
五、不规则窗口
常见的窗体是各种方形的对话框,但有时候也需要非方形的窗体,如圆形,椭圆甚至是不规则形状的对话框。
实现步骤:
1.新建一个项目,比如项目名称叫做“ShapeWidget”,给此项目添加一个类“ShapeWidget”,基类选择“QWidget”。
2.为了使该不规则窗体可以通过鼠标随意拖拽,在类中重定义鼠标事件:mousePressEvent()、mouseMoveEvent()、以及绘制函数paintEvent()
3.“ShapeWidget”的构造函数部分是实现该不规则窗体的关键,添加具体代码如下:
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//去窗口边框
setWindowFlags(Qt::FramelessWindowHint | windowFlags());
//把窗口背景设置为透明,通过透明已经将窗口设置为图片的样式了,窗口和透明图片一样,当然就是不规则窗口了
setAttribute(Qt::WA_TranslucentBackground);
//注意,此时无法移动鼠标以及无法关闭整个特殊的窗口,所以需要重写这些事件
//注意,移动窗口是行对于屏幕而言的,所以鼠标的坐标获取是相对于窗口左上角而言的差值,移动也是移动到左上角。(移动的时候是以窗口的左上角移动的)
}
4.重新实现鼠标事件和绘制函数
void Widget::mousePressEvent(QMouseEvent *e)
{
if(e->button() == Qt::RightButton)
{
//如果是右键,关闭窗口
close();
}
else if(e->button() == Qt::LeftButton)
{
//求坐标差值
//坐标差值=当前点击坐标-窗口左上角坐标 //之所以不用表示相对于窗口的坐标e->x/y,是因为这个e->x/y是相对于窗口的内边框,而移动的是外边框
p = e->globalPos() - this->frameGeometry().topLeft();//this->frameGeometry()获取的是当前矩形窗口
//e->globalPos(),当前坐标 全局的,即相对于屏幕左上角的坐标。.topLeft()矩形窗口的左上角坐标
}
}
void Widget::mouseMoveEvent(QMouseEvent *e)
{
if(e->buttons() & Qt::LeftButton)
{
//把当前窗口中心点移动到左上角,即以当前的左上角作为移动后窗口的中心位置
move(e->globalPos() - p);//当前坐标(全局的)减去差值等于左上角坐标(全局的)
//参数里是移动到的位置
}
}
void Widget::paintEvent(QPaintEvent *)
{
QPainter p(this);
p.drawPixmap(0, 0, QPixmap("../Image/sunny.png"));
}
界面编程之QT绘图和绘图设备20180728的更多相关文章
- 界面编程之QT的线程20180731
/*******************************************************************************************/ 一.为什么需 ...
- 界面编程之QT的文件操作20180729
/*******************************************************************************************/ 一.QT文件 ...
- 界面编程之QT窗口系统20180726
/*******************************************************************************************/ 一.坐标系统 ...
- 界面编程之QT的数据库操作20180801
/*******************************************************************************************/ 一.数据库连 ...
- 界面编程之QT的Socket通信20180730
/*******************************************************************************************/ 一.linu ...
- 界面编程之QT的信号与槽20180725
/*******************************************************************************************/ 一.指定父对 ...
- 界面编程之QT的基本介绍与使用20180722
/*******************************************************************************************/ 一.qt介绍 ...
- 界面编程之QT的事件20180727
/*******************************************************************************************/ 一.事件 1 ...
- QT核心编程之Qt线程 (c)
QT核心编程之Qt线程是本节要介绍的内容,QT核心编程我们要分几个部分来介绍,想参考更多内容,请看末尾的编辑推荐进行详细阅读,先来看本篇内容. Qt对线程提供了支持,它引入了一些基本与平台无关的线程类 ...
随机推荐
- HW 2017 12 17可禾大佬神题
好不容易搞来的题目,不写一写怎么行呢. 不过难度真心不高(一小时K掉),都是老题+暴力题,没有欧洲玄学. 再说一句,这试卷是叶可禾出的吧. T1 好老的题目,看到有多组数据我还怕了,以为有更流弊的算法 ...
- C++和python的变量对比
<C++中的this和Python的self对比>基本都是针对函数而言的,从变量的角度看,也有相同之处. C++中,类中定义的变量一般叫做成员变量,或者说是成员属性,它只属于实例对象,只有 ...
- 基于Boost库的HTTP Post函数
两个函数的区别: 提交表单数据和提交文本数据 表单数据: request_stream << "Content-Type: application/x-www-form-urle ...
- Docker-compose部署gitlab中文版
目录 Docker-compose部署gitlab 1.安装Docker 2.安装Docker-compose 3.安装Gitlab Docker-compose部署gitlab 1.安装Docker ...
- libgdx判断actor与circle是否重叠
实质是检测矩形与circle是否重叠 基本函数,判断点是否在circle中 public static boolean IsInside( float x, float y, Circle circl ...
- python3 str或bytes转换函数
str或bytes始终返回为str #!/usr/bin/env python # -*- coding: utf-8 -*- def to_str(bytes_or_str): if isinsta ...
- [BZOJ3809]Gty的二逼妹子序列[莫队+分块]
题意 给出长度为 \(n\) 的序列,\(m\) 次询问,每次给出 \(l,r,a,b\) ,表示询问区间 \([l,r]\) 中,权值在 \([a,b]\) 范围的数的种类数. \(n\leq 10 ...
- web网站的并发量级别
web网站的并发量级别 评价一个网站的“大小”,处于视角的不同,有很多种衡量的方法,类似文章数,页面数之类的数据非常明显,也没有什么可以争议的.但对于并发来说,争议非常之多,这里就从一个技术的角度开始 ...
- 软件测试_Loadrunner_APP测试_性能测试_脚本优化_脚本回放
本文主要写一下在使用Loadrunner录制完毕APP脚本之后如何对脚本进行回放,如有不足,欢迎评论补充. 如没有安装Loadrunner软件,请查看链接:软件测试_测试工具_LoadRunner: ...
- 集美大学1414班软件工程个人作业2——个人作业2:APP案例分析
一.作业链接 个人作业2:APP案例分析 二.博文要求 通过分析你选中的产品,结合阅读<构建之法>,写一篇随笔,包含下述三个环节的所有要求. 第一部分 调研, 评测 下载软件并使用起来, ...