Qt__绘制系统

Qt绘制系统简介

Qt 的绘图系统允许使用相同的 API 在屏幕和其它打印设备上进行绘制。整个绘图系统基于QPainter,QPainterDevice和QPaintEngine三个类。

  • QPainter用来执行绘制的操作;
  • QPaintDevice是一个二维空间的抽象,这个二维空间允许QPainter在其上面进行绘制,也就是QPainter工作的空间;
  • QPaintEngine提供了画笔(QPainter)在不同的设备上进行绘制的统一的接口。QPaintEngine类应用于QPainter和QPaintDevice之间,通常对开发人员是透明的。除非你需要自定义一个设备,否则你是不需要关心QPaintEngine这个类的。

我们可以把QPainter理解成画笔;把QPaintDevice理解成使用画笔的地方,比如纸张、屏幕等;而对于纸张、屏幕而言,肯定要使用不同的画笔绘制,为了统一使用一种画笔,我们设计了QPaintEngine类,这个类让不同的纸张、屏幕都能使用一种画笔。

程序

main.cpp

#include <QApplication>
#include "paint.h"

int main(int argc, char **argv) {
    QApplication a(argc, argv);
    PaintedWidget mywindow;
    mywindow.show();
    return a.exec();
}

paint.h

#include <QWidget>
#include <QPainter>

class PaintedWidget : public QWidget
{
    Q_OBJECT
public:
    PaintedWidget(QWidget *parent = 0);
protected:
    void paintEvent(QPaintEvent *);
};

paint.cpp

#include "paint.h"
PaintedWidget::PaintedWidget(QWidget *parent) :
    QWidget(parent)
{
    resize(400, 400);
    setWindowTitle(tr("Paint Demo"));
}

void PaintedWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QPen pen(Qt::green, 3, Qt::DashDotLine, Qt::RoundCap, Qt::RoundJoin);
    painter.setPen(pen);
    painter.drawLine(80, 100, 300, 300);
    painter.setPen(Qt::red);
    painter.drawRect(10, 10, 100, 300);
    painter.setPen(QPen(Qt::green, 5));
    painter.setBrush(Qt::blue);
    painter.drawEllipse(50, 150, 200, 100);
}

在构造函数中,我们仅仅设置了窗口的大小和标题。

paintEvent()函数则是绘制的代码。首先,我们在栈上创建了一个QPainter对象,也就是说,每次运行paintEvent()函数的时候,都会重建这个QPainter对象。QPainter接收一个QPaintDevice指针作为参数。QPaintDevice有很多子类,比如QImage,以及QWidget。QPaintDevice可以理解成要在哪里去绘制,而现在我们希望画在这个组件,因此传入的是 this 指针。

注意,这一点可能会引发某些细节问题:由于我们每次重建QPainter,因此第一次运行时所设置的画笔颜色、状态等,第二次再进入这个函数时就会全部丢失。有时候我们希望保存画笔状态,就必须自己保存数据,否则的话则需要将QPainter作为类的成员变量。paintEvent() 作为重绘函数,会在需要重绘时由 Qt 自动调用。“需要重绘”可能发生在很多地方,比如组件刚刚创建出来的时候就需要重绘;组件最大化、最小化的时候也需要重新绘制;组件由遮挡变成完全显示的时候也需要等等。

程序运行结果

画刷和画笔

Qt 绘图系统定义了两个绘制时使用的关键属性:画刷和画笔。前者使用QBrush描述,大多用于填充;后者使用QPen描述,大多用于绘制轮廓线。

画刷

  • 画刷的style()定义了填充的样式,使用Qt::BrushStyle枚举,默认值是Qt::NoBrush,也就是不进行任何填充。我们可以从下面的图示中看到各种填充样式的区别:

  • 画刷的color()定义了填充模式的颜色。这个颜色可以是 Qt 预定义的颜色常量,也就是Qt::GlobalColor,也可以是任意QColor对象。
  • 画刷的gradient()定义了渐变填充。这个属性只有在样式是Qt::LinearGradientPattern、Qt::RadialGradientPattern或者Qt::ConicalGradientPattern之一时才有效。渐变可以由QGradient对象表示。Qt 提供了三种渐变:QLinearGradient、QConicalGradient和QRadialGradient,它们都是QGradient的子类。我们可以使用如下代码片段来定义一个渐变的画刷:
        QPainter painter(this);
        QLinearGradient linearGradient(200, 50, 300, 50);
        linearGradient.setColorAt(0, Qt::red);
        linearGradient.setColorAt(1, Qt::green);
        painter.setBrush(linearGradient);
        painter.drawEllipse(QPointF(250, 50), 50, 50);
    
        QRadialGradient radialGradient(QPointF(50, 50), 50, QPointF(50, 50));
        radialGradient.setColorAt(0, QColor(255, 255, 100, 150));
        radialGradient.setColorAt(1, QColor(0, 0, 0, 50));
        painter.setBrush(radialGradient);
        painter.drawEllipse(QPointF(50, 50), 50, 50);
    
        QConicalGradient conicalGradient(QPointF(150, 50), 60);
        conicalGradient.setColorAt(0.2, Qt::white);
        conicalGradient.setColorAt(0.9, Qt::black);
        painter.setBrush(conicalGradient);
        painter.drawEllipse(QPointF(150, 50), 50, 50);

    运行结果如下:

  • 画刷样式是 Qt::TexturePattern时,texture()定义了用于填充的纹理。注意,即使你没有设置样式为Qt::TexturePattern,当你调用setTexture()函数时,QBrush会自动将style()设置为Qt::TexturePattern。

    QPainter painter(this);
    QBrush brush;
    brush.setTexture(QPixmap("image.jpg"));
    painter.setBrush(brush);
    painter.drawEllipse(50, 100, 300, 200);

    运行结果:

画笔

QPen定义了用于QPainter应该怎样画线或者轮廓线。

画笔具有样式、宽度、画刷、笔帽样式和连接样式等属性。

  • 1.画笔的样式style()定义了线的样式。画刷brush()用于填充画笔所绘制的线条。
  • 2.笔帽样式capStyle()定义了使用QPainter绘制的线的末端;
  • 3.连接样式joinStyle()则定义了两条线如何连接起来。
  • 4.画笔宽度width()或widthF()定义了画笔的宽。注意,不存在宽度为 0 的线。

    注:假设你设置 width 为 0,QPainter依然会绘制出一条线,而这个线的宽度为 1 像素。也就是说,画笔宽度通常至少是 1 像素。

这么多参数既可以在构造时指定,也可以使用 set 函数指定,完全取决于你的习惯,例如:

QPainter painter(this);
QPen pen(Qt::green, 3, Qt::DashDotLine, Qt::RoundCap, Qt::RoundJoin);
painter.setPen(pen);

等价于

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);

使用构造函数的优点是代码较短,但是参数含义不明确;使用 set 函数则正好反过来。

默认的画笔属性是纯黑色,0 像素,方形笔帽(Qt::SquareCap),斜面型连接(Qt::BevelJoin)。

1.下面是画笔样式的示例:

你也可以使用setDashPattern()函数自定义样式,例如如下代码片段:

 QPen pen;
 QVector<qreal> dashes;
 qreal space = 4;
 dashes << 1 << space << 3 << space << 9 << space
        << 27 << space << 9 << space;
 pen.setDashPattern(dashes);

2.笔帽定义了画笔末端的样式,例如:

他们之间的区别是,Qt::SquareCap是一种包含了最后一个点的方形端点,使用半个线宽覆盖;Qt::FlatCap不包含最后一个点;Qt::RoundCap是包含最后一个点的圆形端点。具体可以参考下面的示例(出自《C++ GUI Programming with Qt 4, 2nd Edition》):

3.连接样式定义了两条线连接时的样式,例如:

同样,可以参考下面图示来理解这几种连接样式的细节(出自《C++ GUI Programming with Qt 4, 2nd Edition》):

参考

豆子空间

原文地址:https://www.cnblogs.com/narjaja/p/9153206.html

时间: 2024-11-10 13:08:11

Qt__绘制系统的相关文章

QT绘制系统简介

#3个类:QPainter,QPainterDevice 和 QPaintEngine 三个类 #qpainter用于执行绘制操作 #QPainterDevice是一个二维空间抽象,允许qpainter在其上面进行绘制,也就是qpainter工作空间 #QPaintEngine 提供了画笔(qpainter)在不同设备上进行绘制统一接口,QPaintEngine类应用于QPainter和QPaintDevice 之间,如果需要自定义一个设备时 #则不需要关心QPaintEngine 这个类的QP

图形绘制系统的体系结构总结

最初制作图形系统的目的是什么? 最初,制作专用图形系统的目的主要是为了把通用计算机从不间断刷新显示器的任务中解放出来.在主计算机与显示器之间增加的显示处理器模块,具有传统的体系结构,但增加了在显示器显示图元的指令.这样生成图像的指令可以在主计算机中集中存储,然后发送到显示处理器.这些指令可以作为显示列表存储到显示处理器自己的存储器中.然后,显示处理器会以足够的速率来重复的执行显示列表中的指令,从而避免闪烁,这样主计算机就可以执行其他任务了. 什么是系统的吞吐量? 数据通过系统的速率,称为系统的吞

Qt 学习之路 :Qt 绘制系统简介

Qt 的绘图系统允许使用相同的 API 在屏幕和其它打印设备上进行绘制.整个绘图系统基于QPainter,QPainterDevice和QPaintEngine三个类. QPainter用来执行绘制的操作:QPaintDevice是一个二维空间的抽象,这个二维空间允许QPainter在其上面进行绘制,也就是QPainter工作的空间:QPaintEngine提供了画笔(QPainter)在不同的设备上进行绘制的统一的接口.QPaintEngine类应用于QPainter和QPaintDevice

使用调色板绘制系统界面

相关代码可视频可在网易云课堂下载: Linux kernel Hacker, 从零构建自己的内核 上一节,我们已经可以使用C语言实现图像绘制,但操作系统的用户界面不可能是那种扎眼的条纹图案,这一节,我们要改进图形绘制的方法,做一个像某像样的系统界面. 上一节,我们实现图像绘制的办法是,给每一个像素设定指定的数值,这个数值只能位于0-256这个范畴,以现在绚丽多彩的UI效果来说,256种颜色显然是不够用的,而且还不论颜色的亮度,饱和度等这些成分呢.能够比较好的表示颜色的,一般都使用RGB模式,表示

绘制系统地图路线

#import "ViewController.h" #import <MapKit/MapKit.h> #import <CoreLocation/CoreLocation.h> @interface ViewController () /** 地理编码 */ @property (nonatomic, strong) CLGeocoder *geoC; @end @implementation ViewController #pragma mark -懒加载

一点在绘制系统架构图时的思考

系统架构图类似于工程师的设计图纸,是凌驾于代码细节的更高层次.代码确实不值钱,价值所在就是你的思路.你的功能.狭义一点的话 就是你的算法. 研究层面,就是你的算法,你的价值是,你加速了多少:工程层面,就是你的功能,你的功能方便了哪些工作.这就是一个工程师要去思考的东西.至于代码,真的是考虑主流和兼容性即可 你的文章值多少钱 和你用红色笔写还是蓝色笔写,没太大关系,当然在工程的角度,不同的语言和实现方法会带来性能的差异 .但是这一是属于设计层面,工程师和建筑师是一样的,你本来报建筑设计师,你觉得画

关于系统首页绘制问题(ext布局+c#后台添加数据)经html输出流输出响应客户端

关于系统首页绘制问题,业务需求: TODO: 1,绘制系统首页(Main.aspx) 2,采用的技术:functioncharts+jquery+ext布局+c#+html 讲解篇:1,服务端aspx,2,服务端后台返回数据(这里采用服务器端程序:aspx.cs) 1,服务端aspx <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Main.aspx.cs" Inherit

智能家居系统-硬件设计

1. 主控板设计 采用Altium Designer 09绘制系统PCB图, PCB图通过了设计规则检查(DRC),保证电气连接的正确性.PCB图采用手动布线的方式,在布线布局方面进行了优化.PCB图如图4-16所示,3D图如图4-17所示.焊接完成的PCB实物图如图4-18所示. 图4-16 中央控制器PCB图 3D视图 图1-17  中央控制器PCB的3D图 2. 学习型红外遥控器设计 学习型遥控器(万遥)的功能主要分为学习和发送两个部分.在学习的过程中,万遥接收到用户的家电遥控器所发送过来

实现系统滚动条换肤功能

http://blog.sina.com.cn/s/blog_4c3538470100gews.html 1 实现系统滚动条换肤功能 对于Windows系统中各种控件换肤功能,要数滚动条的换肤最难实现了,尤其是控件自带的系统滚动条,如Edit.ListBox.ListView.TreeView等自带的系统滚动条,要想实现其自定义的皮肤功能,用常规办法似乎都无法实现. 对于常规的皮肤定制一般都是通过定制WM_PAINT.WM_ERASEBKGND.WM_CTLCOLORxxx.NM_CUSTOMD