Tudou

博客园 首页 新随笔 联系 订阅 管理
Qt的文档位置为 Paint System
 
大纲:
    简介
    先看一个小例子
    基本的绘制和填充
        使用画笔(Qpen)
        使用画刷(QBrush)
        渐变填充
 
简介
Qt中提供了强大的2D绘图系统,可以使用相同的API在屏幕和绘图设备上进行绘制,
主要基于QPainter、QPaintDevice和QPaintEngine这3个类。
 
QPainter用来执行绘图操作。
 
QPaintDevice 提供绘图设备,是一个二维空间的抽象,可以使用QPainter在其上进行绘制,也就是QPainter工作的空间。
QPaintDevice是所有可以进行绘制的对象的基类,它的子类主要有QWidget、QPixmap、QPicture、QImage、QPrinter和QOpenGLPaintDevice等。
 
QPaintEngine提供了画笔(QPainter)在不同的设备上进行绘制的统一的接口。
QPaintEngine类应用于QPainter和QPaintDevice之间,通常对开发人员是透明的。除非你需要自定义一个设备,否则你是不需要关心QPaintEngine这个类的。
除了创建自定义的绘图设备类型,一般编程中不需要使用该类。(本篇作为入门文章,就不再讲这个了)
 
我们可以这样理解:
我们可以把QPainter理解成画笔;
把QPaintDevice理解成使用画笔的地方,比如纸张、屏幕等;
而对于纸张、屏幕而言,肯定要使用不同的画笔绘制,为了统一使用一种画笔,我们设计了QPaintEngine类,这个类让不同的纸张、屏幕都能使用一种画笔。
 
下图给出了这三个类之间的层次结构
上面的示意图告诉我们,Qt 的绘图系统实际上是,使用QPainterQPainterDevice上进行绘制,它们之间使用QPaintEngine进行通讯(也就是翻译QPainter的指令)。
 
先看一个基本例子
class PaintedWidget : public QWidget
{
    Q_OBJECT
public:
    PaintedWidget(QWidget *parent = 0);
protected:
    void paintEvent(QPaintEvent *)override;
};
 
PaintedWidget::PaintedWidget(QWidget *parent) :
    QWidget(parent)
{
    resize(800, 600);
    setWindowTitle(tr("Paint Demo"));
}
 
 
// 绘制
void PaintedWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.drawLine(80, 100, 650, 500);
    painter.setPen(Qt::red); // setPen 设置轮廓线的颜色
    painter.drawRect(10, 10, 100, 400);
    painter.setPen(QPen(Qt::green, 5));
    painter.setBrush(Qt::blue); // brush是画刷,是填充颜色
    painter.drawEllipse(50, 150, 400, 200);
}
首先,我们在栈上创建了一个QPainter对象,也就是说,每次运行paintEvent()函数的时候,都会重建这个QPainter对象。
注意,这一点可能会引发某些细节问题:由于我们每次重建QPainter,因此第一次运行时所设置的画笔颜色、状态等,
第二次再进入这个函数时就会全部丢失。有时候我们希望保存画笔状态,就必须自己保存数据,否则的话则需要将QPainter作为类的成员变量。
 
基本的绘制和填充
绘图系统中由QPainter完成具体的绘制操作其中,提供了大量高度优化的函数(一般draw开头)来完成GUI编程所需要的大部分绘工作
QPainter可以绘制一切想要的图形,从最简单的一条直线到其他任何复杂的图形,还可以绘制文本和图片。
QPainter可以在继承自QPaintDevice类的任何对象上进行绘制操作(QWidget,QImage等),QPaintDevice可以理解成要在哪里去绘制。(对于上例子的中,我们希望画在这个组件,因此传入的是 this 指针。)
 
QPainter一般在一个部件重绘事件(Paint Event)的处理函数paintEvent()中进行绘制,首先要创建QPainter对象,然后进行图形的绘制,最后销毁QPainter对象。
 
绘制图形
// 方式1
void Widget::paintEvent(QPaintEvent *){
    QPainter painter(this); 
    painter.drawLine(80, 100, 650, 500);
    // 或者下面 (drawLine有)
    painter.drawLine(QPoint(0,0),QPoint(100,100));
}
 
//方式2 ,与上面等价
void Widget::paintEvent(QPaintEvent *) {
    QPainter painter;
    painter.begin(this);
    painter.drawLine(QPoint(0,0),QPoint(100,100));
    painter.end();
}
 
第一种方式创建时并指定了this为绘图设备,即表明在Widget部件上进行绘制。这个构造函数创建的对象会立即开始在设备上进行绘制,自动调用begin()函数,然后在QPainter的析构函数中调用end()函数结束绘制。
 
第二种:如果构建QPainter对象时不想指定绘制设备,那么可以使用不带参数的构造函数,然后使用QPainter:: begin(QPaintDevice *device)在开始绘制时指定绘制设备,等绘制完成后再调用end()函数结束绘制。
 
常用的绘制方法
 
使用画笔(QPen)
The QPen class defines how a QPainter should draw lines and outlines of shapes.(QPen类定义QPainter应该如何绘制形状的线条和轮廓)
详细内容请看doc
For example:
  QPainter painter(this);
  QPen pen(Qt::green, 3, Qt::DashDotLine, Qt::RoundCap, Qt::RoundJoin);
 
 
  painter.setPen(pen);
 
which is equivalent to
 
  QPainter painter(this);
  QPen pen;  // creates a default pen
  
  pen.setStyle(Qt::DashDotLine);
  pen.setWidth(3);
  pen.setBrush(Qt::green);
  pen.setCapStyle(Qt::RoundCap);
  pen.setJoinStyle(Qt::RoundJoin);
  painter.setPen(pen);
 
QPen(const QBrush &brush, qreal width, Qt::PenStyle style = Qt::SolidLine, Qt::PenCapStyle cap = Qt::SquareCap, Qt::PenJoinStyle join = Qt::BevelJoin)
这个构造函数参数依次是画刷,线宽,画笔风格,画笔端点风格和画笔连线风格。
然后使用painter的setPen()来设置画笔。
 
Pen Style(画笔风格)
还可以使用setDashPattern()函数来自定义一个画笔风格。
doc有说明
 QPen pen;
  QVector<qreal> dashes;
  qreal space = 4;
  dashes << 1 << space << 3 << space << 9 << space
             << 27 << space << 9 << space;
  pen.setDashPattern(dashes);
 
Cap Style(画笔端点风格) The default is Qt::SquareCap.
 
Join Style(画笔连接风格) The default is Qt::BevelJoin.
画笔连接风格定义了怎样绘制两个线条的连接。
其中,Qt::BeveJoin风格填充了两个线条之间的空缺三角形;
而Qt:: RoundJoin使用圆弧来填充这个三角形,这样显得更圆滑;
使用Qt:: MiterJoin风格,是将两个线条的外部边线进行扩展而相交,然后填充形成的三角形区域。
注意:这3种风格对于宽度为0的线条没有作用,可以把很宽的线条看作一个矩形来理解这3种风格,如下:
 
 
使用画刷(QBrush)
QBrush类提供了画刷来对图形进行填充,一个画刷使用它的颜色和风格(比如它的填充模式)来定义。
在Qt中使用的颜色一般都由QColor类(此类与平台无关)来表示,它支持RGB、HSV和CMYK等颜色模型。Qt提供了20多种的预定义颜色。
 
渐变填充(QGradinet) 详细查看和派生的三个类 
上面提到了在画刷中可以使用渐变填充。QGradient类就是用来和QBrush一起指定渐变填充的。
Qt现在支持3种类型的渐变填充:
线性渐变(linear gradient):在开始点和结束点之间插入颜色;(QLineGradient)
辐射渐变(radialgradient):在焦点和环绕它的圆环间插人颜色;(QRadialGradient)
锥形渐变(Conical):在圆心周围插入颜色(QConicalGradient)
 
posted on 2020-06-02 15:32  JindouBlog  阅读(1234)  评论(0编辑  收藏  举报