C++ GUI Qt4学习笔记(八)

    本章介绍Qt的二维图形引擎,Qt的二维图形引擎是基于QPainter类的。QPainter既可以绘制几何图形(点、线、矩形等),也可以绘制像素映射、图像和文字。此外QPainter还支持一些高级特性,例如反走样、像素混合、渐变填充和矢量路径等。QPainter也支持线性变换,例如平移、旋转、错切和缩放。

        QPainter可以画在“绘图设备”(QWidget、QPixmap、QImage和QSvgGenerator)上,也可以与QPrinter一起使用来打印文件和创建PDF文档。

        重新实现QWidget::PaintEvent()可用于定制窗口部件,随心所欲的控制他们的外观

        一项普通的需求是在二维画板上显示大量的、轻量级的、可以用户交互的、任意形状的项。

        可使用OpenGL命令来代替QPainter。OPenGL是一个绘制三维图形的标准库。

8.1用QPainter绘图

        想要在绘图设备上绘图,只需要创建一个QPainter,在将指针传到该设备中。

        使用QPainter的draw...()函数,可以绘制各种各样的形状。绘制的效果取决于QPainter的设置。三个主要的设置是画笔、画刷、字体:

                ①画笔用来画线和边缘。QPen,设置属性setPen()

                ②画刷用来填充几何形状的图案。QBrush,设置属性setBrush()

                ③字体用来绘制文字。QFont,设置属性setFont()

绘制椭圆:

QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
painter.setPen(QPen(Qt::black,12,Qt::DashDotLine,Qt::RoundCap));
painter.setBrush(QBrush(Qt::green,Qt::SolidPattern));
painter.drawEllipse(80,80,400,240);

setRenderHint(QPainter::Antialiasing,true)可以启用反走样,可在支持这一特性的平台和设备上得到平滑的边缘。

QPainterPath类可以通过连接基本的图形元素来确定任意的矢量图形:直线、椭圆、多边形等绘制路径。绘制路劲是基本的图元,任何图形或图形组合都可以用绘制路径描述。路径可以确定一个边缘,由边缘锁定的区域可以用画刷来填充。

        在现代应用中,渐变填充已成为单色填充的流行替代品。渐变填充利用颜色差值使得两个或更多颜色之间能够平滑的过度。

        Qt支持3种类型的渐变:

            线性渐变,由两个控制点定义,连接这两点的线上有一系列的颜色断点。

            锥形渐变,由一个中心点和一个角度定义。

            辐射渐变,由一个中心点、半径、一个焦点,以及颜色断点定义。颜色由焦点向外扩散,焦点可以是中心点或者圆内的其他点。

QPainter还有其他影响图形和文字绘制方式的设置这里不详细介绍了。

8.2坐标系统变换       
        在QPainter的默认坐标系中,点(0,0)位于绘图设备的左上角,x坐标向右增长,y坐标向下增长。默认坐标系的每个像素占1x1大小的区域。

        理论上像素的中心取决于半像素坐标,一个像素正好位于四个像素的重合处。如果不需要这种效果,可以通过制定半像素坐标或者通过便宜QPainter(+0.5,+0.5)来避免这种效果的出现。

        QPainter的视口,是物理坐标系下制定的任意矩形。

        QPainter的窗口也是指同一矩形,只不过是在逻辑坐标系下。这种窗口-视口机制对于编写独立于绘制设备大小和分辨率的绘制代码是有用的。

        世界变换是在窗口-视口转换之外使用的变换矩阵。它允许移动、缩放、旋转或者拉伸绘制的项。

OvenTimer窗口部件代码

        这个OvenTimer模仿烤箱的定时器,它是烤箱内置的钟表。用户可以单击刻度来设置持续时间。转轮会自动的逆时针转到0,OvenTimer在这一点发射timeout()信号。

ovenTimer.h

#ifndef OVENTIMER_H
#define OVENTIMER_H

#include <QDateTime>
#include <QWidget>

class QTimer;

class OvenTimer : public QWidget
{
    Q_OBJECT

public:
    OvenTimer(QWidget *parent = 0);

    void setDuration(int secs);
    int duration() const;
    void draw(QPainter *painter);

signals:
    void timeout();

protected:
    void paintEvent(QPaintEvent *event);
    void mousePressEvent(QMouseEvent *event);

private:
    QDateTime finishTime;
    QTimer *updateTimer;
    QTimer *finishTimer;
};

#endif

oventimer.cpp

#include <QtGui>
#include <cmath>

#ifndef M_PI
#define M_PI 3.14159265359
#endif

#include "oventimer.h"

const double DegreesPerMinute = 7.0;
const double DegreesPerSecond = DegreesPerMinute / 60;
const int MaxMinutes = 45;
const int MaxSeconds = MaxMinutes * 60;
const int UpdateInterval = 5;

OvenTimer::OvenTimer(QWidget *parent)
    : QWidget(parent)
{
    finishTime = QDateTime::currentDateTime();	//获取当前时间

    updateTimer = new QTimer(this);	
    connect(updateTimer, SIGNAL(timeout()), this, SLOT(update()));

    finishTimer = new QTimer(this);
    finishTimer->setSingleShot(true);
    connect(finishTimer, SIGNAL(timeout()), this, SIGNAL(timeout()));
    connect(finishTimer, SIGNAL(timeout()), updateTimer, SLOT(stop()));

    QFont font;
    font.setPointSize(8);	//设置窗口字体的大小
    setFont(font);
}

void OvenTimer::setDuration(int secs)	//设置了烤箱定时器的持续时间为给定的秒数。
{
    secs = qBound(0, secs, MaxSeconds);	//防止越界0~MaxSeconds

    finishTime = QDateTime::currentDateTime().addSecs(secs);

    if (secs > 0) {
        updateTimer->start(UpdateInterval * 1000);
        finishTimer->start(secs * 1000);
    } else {
        updateTimer->stop();
        finishTimer->stop();
    }
    update();
}

int OvenTimer::duration() const	//获取定时器完成前剩余的秒数。
{
    int secs = QDateTime::currentDateTime().secsTo(finishTime);
    if (secs < 0)
        secs = 0;
    return secs;
}

void OvenTimer::mousePressEvent(QMouseEvent *event)
{
    QPointF point = event->pos() - rect().center();
    double theta = std::atan2(-point.x(), -point.y()) * 180.0 / M_PI;
    setDuration(duration() + int(theta / DegreesPerSecond));
    update();
}

void OvenTimer::paintEvent(QPaintEvent * /* event */)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);

    int side = qMin(width(), height());	//返回两个参数中较小的一个

    painter.setViewport((width() - side) / 2, (height() - side) / 2,
                        side, side);
    painter.setWindow(-50, -50, 100, 100);

    draw(&painter);
}

void OvenTimer::draw(QPainter *painter)
{
    static const int triangle[3][2] = {
        { -2, -49 }, { +2, -49 }, { 0, -47 }
    };
    QPen thickPen(palette().foreground(), 1.5);	//palette().foreground()得到笔刷
    QPen thinPen(palette().foreground(), 0.5);
    QColor niceBlue(150, 150, 200);

    painter->setPen(thinPen);
    painter->setBrush(palette().foreground());
    painter->drawPolygon(QPolygon(3, &triangle[0][0]));

    QConicalGradient coneGradient(0, 0, -90.0);
    coneGradient.setColorAt(0.0, Qt::darkGray);
    coneGradient.setColorAt(0.2, niceBlue);
    coneGradient.setColorAt(0.5, Qt::white);
    coneGradient.setColorAt(1.0, Qt::darkGray);

    painter->setBrush(coneGradient);
    painter->drawEllipse(-46, -46, 92, 92);

    QRadialGradient haloGradient(0, 0, 20, 0, 0);
    haloGradient.setColorAt(0.0, Qt::lightGray);
    haloGradient.setColorAt(0.8, Qt::darkGray);
    haloGradient.setColorAt(0.9, Qt::white);
    haloGradient.setColorAt(1.0, Qt::black);

    painter->setPen(Qt::NoPen);
    painter->setBrush(haloGradient);
    painter->drawEllipse(-20, -20, 40, 40);

    QLinearGradient knobGradient(-7, -25, 7, -25);
    knobGradient.setColorAt(0.0, Qt::black);
    knobGradient.setColorAt(0.2, niceBlue);
    knobGradient.setColorAt(0.3, Qt::lightGray);
    knobGradient.setColorAt(0.8, Qt::white);
    knobGradient.setColorAt(1.0, Qt::black);

    painter->rotate(duration() * DegreesPerSecond);
    painter->setBrush(knobGradient);
    painter->setPen(thinPen);
    painter->drawRoundRect(-7, -25, 14, 50, 99, 49);

    for (int i = 0; i <= MaxMinutes; ++i) {
        if (i % 5 == 0) {
            painter->setPen(thickPen);
            painter->drawLine(0, -41, 0, -44);
            painter->drawText(-15, -41, 30, 30,
                              Qt::AlignHCenter | Qt::AlignTop,
                              QString::number(i));
        } else {
            painter->setPen(thinPen);
            painter->drawLine(0, -42, 0, -44);
        }
        painter->rotate(-DegreesPerMinute);
    }
}


8.3用QImage高质量绘图

绘图时,我们可能需要面对速度和准确率的折中问题

C++ GUI Qt4编程(第二版)》一书所有源代码下载地址:http://download.csdn.net/source/3402597。 《C++ GUI Qt4编程(第二版)》,英文名《C++ GUI Programming with Qt4,Second Edition》,作者:【加拿大】Jasmin Blanchette、【英】Mark Summerfield,翻译:闫锋欣、曾泉人、张志强,审校:周莉娜、赵延兵,出版社:电子工业出版社,ISBN:9787121070389,PDF 格式,大小 155Mb。被压缩为 3 部分,本资源是第一部分:第一部分下载地址:http://download.csdn.net/source/3397783;第二部分下载地址:http://download.csdn.net/source/3397770;第三部分下载地址:http://download.csdn.net/source/3397766。 三个资源在一起解压缩后(windows 平台下解压缩)即可得到《C++ GUI Qt4编程(第二版)》.pdf 一书。 内容简介: 本书详细讲述了用最新的qt版本进行图形用户界面应用程序开发的各个方面。前5章主要涉及qt基础知识,后两个部分主要讲解qt的中高级编程,包括布局管理、事件处理、二维/三维图形、拖放、项视图类、容器类、输入/输出、数据库、多线程、网络、xml、国际化、嵌入式编程等内容。对于本书讲授的大量qt4编程原理和实践,都可以轻易将其应用于qt4.4、qt4.5以及后续版本的qt程序开发过程中。   本书适合对qt编程感兴趣的程序员以及广大计算机编程爱好者阅读,也可作为相关机构的培训教材。 目录: 第一部分 qt基础  第1章 qt入门                   第2章 创建对话框           第3章 创建主窗口                  第4章 实现应用程序的功能        第5章 创建自定义窗口部件      第二部分 qt中级  第6章 布局管理  第7章 事件处理  第8章 二维图形  第9章 拖放  第10章 项视图类  第11章 容器类  第12章 输入与输出  第13章 数据库  第14章 多线程  第15章 网络  第16章 xml  第17章 提供在线帮助 第三部分 qt高级 . 第18章 国际经  第19章 自定义外观  第20章 三维图形  第21章 创建插件  第22章 应用程序脚本  第23章 平台相关特性  第24章 嵌入性编程第四部分  附录
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奔跑吧小考拉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值