前沿

很多很好看的控件,都不是通过样式表设定样式出现的,而是通过自绘控件或者QStyle或者代理,这几种方式,都会有QPainter的出现!对于一个widget,只能有一个激活的QPainter进行绘制,会打架的!设定有两种方式,一种是构造函数,一种是begin。

  • QT没有采用二维笛卡尔坐标,以屏幕左上角为原点,向右为X+,向下为Y+。可以使用setWindow实现,

一、API

函数名 意义
QPainter();
explicit QPainter(QPaintDevice *); 构造并且指定绘制的控件
QPaintDevice *device() const; 返回指定的控件
bool begin(QPaintDevice *); 在该控件绘制
bool end(); 结束绘制
bool isActive() const; 是否绘制
void initFrom(const QPaintDevice *device); 以device初始化pen font background
const QFont &font() const; 绘制字体时的字体
void setFont(const QFont &f); 指定一个字体
void setPen(const QColor &color); 几种设定画笔的方式
void setPen(const QPen &pen);
void setPen(Qt::PenStyle style);
const QPen &pen() const;
void setBrush(const QBrush &brush); 设定QBrush 用于指定填充颜色
void setBrush(Qt::BrushStyle style); 不需要时可以 setBrush(Qt::NoBrush)
const QBrush &brush() const;
void setBackgroundMode(Qt::BGMode mode); 设定透明或者不透明模式 没用过 0_0
Qt::BGMode backgroundMode() const;
QPoint brushOrigin() const; 用意不明 设定填充的起点
inline void setBrushOrigin(int x, int y);
inline void setBrushOrigin(const QPoint &);
void setBrushOrigin(const QPointF &);
void setBackground(const QBrush &bg); 设定背景色
const QBrush &background() const;
qreal opacity() const; 设定不透明度
void setOpacity(qreal opacity);
QRegion clipRegion() const; 设定一个区域,只能在该区域绘图 QRegion可以用来求面积相交的部分
QPainterPath clipPath() const;
void setClipRect(const QRectF &, Qt::ClipOperation op = Qt::ReplaceClip);
void setClipRect(const QRect &, Qt::ClipOperation op = Qt::ReplaceClip);
inline void setClipRect(int x, int y, int w, int h, Qt::ClipOperation op = Qt::ReplaceClip);
void setClipRegion(const QRegion &, Qt::ClipOperation op = Qt::ReplaceClip);
void setClipPath(const QPainterPath &path, Qt::ClipOperation op = Qt::ReplaceClip);
void setClipping(bool enable);
bool hasClipping() const;
QRectF clipBoundingRect() const;
void save(); 大有用处!保存和恢复pen brush 变换(rotate,translate,scale,shear)
void restore();
(World Coordinates)==>(Window Coordinates)==>(Device Coordinates)


世界坐标(逻辑坐标) 世界变换 窗口坐标 窗口视图变换 设备坐标 | |
| void setTransform(const QTransform &transform, bool combine = false); | 修改世界变换 替换了setWorldMatrix |
| const QTransform &transform() const; | |
| const QTransform &deviceTransform() const; | |
| void resetTransform(); | |
| void setWorldTransform(const QTransform &matrix, bool combine = false); | |
| const QTransform &worldTransform() const; | |
| void scale(qreal sx, qreal sy); | 缩放 |
| void shear(qreal sh, qreal sv); | 剪切 |
| void rotate(qreal a); | 旋转 |
| void translate(const QPointF &offset); | 平移 |
| inline void translate(const QPoint &offset); | |
| inline void translate(qreal dx, qreal dy); | |
| QRect window() const; | 修改窗口绘图坐标 设定绘图区域范围是多少 如 0,0 100,100 右下角就是100,100 |
| void setWindow(const QRect &window); | |
| inline void setWindow(int x, int y, int w, int h); | |
| QRect viewport() const; | 修改视图绘图坐标 设定绘图区域范围 如 0,0 100,100 那么只在这个矩形内画图,并且100,100这个点对应的范围是 window的右下角 |
| void setViewport(const QRect &viewport); | |
| inline void setViewport(int x, int y, int w, int h); | |
| void setViewTransformEnabled(bool enable); | |
| bool viewTransformEnabled() const; | |
| void scale(qreal sx, qreal sy); | 缩放 |
| void shear(qreal sh, qreal sv); | 扭曲 |
| void rotate(qreal a); | 旋转 |

QPainter内置的一些图形,如果有更多的需求,配合QPainterPath实现

函数名 意义
void strokePath(const QPainterPath &path, const QPen &pen); 绘制path的轮廓
void fillPath(const QPainterPath &path, const QBrush &brush); 绘制path的填充区域
void drawPath(const QPainterPath &path); 绘制path
drawPoint 画一个点
drawPoints 画几个点
drawLine 画一条线
drawLines 画几条线
drawRect 画一个矩形
drawRects 画几个矩形
drawEllipse 画正圆或者椭圆
drawPolyline 画多段线
drawPolygon 画多边形
drawConvexPolygon 画凸多边形
drawArc 画圆弧,参数只能传整数,若画90度,角度参数传90*16
drawPie 画饼图,参数只能传整数,若画90度,角度参数传90*16
drawChord 画弦图
drawRoundedRect 画圆角矩阵,百份比
drawRoundRect 画圆角矩阵,度数
drawPicture 画.pic图片
drawPixmap 画位图 若是QBitmap则是使用pen的颜色绘制 QPixmap则使用原图
drawPixmapFragments 同时绘制多个pixmax或者子图 带优化
drawImage 画QImage

二、简单使用

1
2
3
4
5
6
7
8
9
10
11
//实现父类虚函数
void paintEvent(QPaintEvent *e){
//一
QPainter painter(this);

//二
QPainter painter;
painter.begin(this);

painter.end();
}

三、QT坐标转笛卡尔坐标(setWindow,setViewport)

1
2
3
4
5
6
7
8
9
10
11
因为QT的QPainter坐标是以左上角为原点,与迪卡尔坐标不一样,所以我当时做的操作是
x=_x;
y=(-_y)+height(); y轴先与x轴对称,然后平衡一个屏幕的高度,完成转换笛卡尔坐标操作 当然这也有好处,全部东西都由自己控制

二、
void setWindow(const QRect &window);
void setViewport(const QRect &viewport);
最近才发现这两个函数,这样解释一下,setWindow有四个参数x,y,w,h,前两个参数是设定图像左上角的坐标,右角坐标为 x+w,y+h 用这个函数可以直接实现笛卡尔坐标系(左下角为原点)
setWindow(0,height(),width(),-height()); 这个意思体会体会

setViewport 就是设定绘画的区域 目前没有找到哪里合适用

四、类中子控件绘制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
子控件是QWidget的派生类:
在类中重写void paintEvent(QPaintEvent *e);进行相应的绘制就行

子控件不是QWidget的派生类,但是想在类中绘制,可以使用拦截事件:
QWidget *paintWidget=new QWidget();
paintWidget->installEventFilter(this);
接着重载事件过滤事件
bool eventFilter(QObject *o, QEvent *e){
if(o==paintWidget){
if(e->type()==QEvent::Paint){
mPainterWidget(paintWidget);
return true;
}
}
return QWidget::eventFilter(o,e);
}

void mPainterWidget(QWidget *w){
QPainter painter(w);
//draw somthing
}

五、画一个带角度的椭圆

1
2
3
4
5
6
7
8
9
10
当初好奇,想画一个带角度的椭圆,发现图形画圆的
drawEllipse 没有带角度的参数,只有一个外接矩形
后面又发现QPainter自带一个角度旋转(顺时针) 舒服
void translate(const QPointF &offset);
void rotate(qreal a);
步骤:
painter.translate(x,y); 因为角度旋转是以原点旋转,所以先将坐标点平移到椭圆中心
painter.rotate(15); 旋转角度
painter.drawEllipse(x-w/2,y-h/2,w,h);
painter.resetTransform(); 恢复原来