《QT Creator快速入门》第十章:2D绘制(3)

摘要:
②、一般是使用QPixmap加载和显示图像,如果需要提前对图像进行操作的话,先用QImage加载图片,对图片数据进行操作,然后将Qimage转换为QPixmap对象来显示图片。QPixmap的fill()函数可以使用指定的颜色初始化整个pixmap图像,还可以使用grabWindows()和grabWidget()等静态函数来实现截取屏幕、截取窗口部件上内容功能。

1、绘制文字

使用QPainter::drawText()来绘制文字:

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    QRectF rect(10.0, 10.0, 580.0, 280.0);
    painter.setPen(Qt::red);
    painter.drawRect(rect);

    painter.setPen(Qt::blue);
    painter.drawText(rect, Qt::AlignHCenter, "alignHCenter");
    painter.drawText(rect, Qt::AlignLeft, "alignLeft");
    painter.drawText(rect, Qt::AlignRight, "alignRight");
    painter.drawText(rect, Qt::AlignVCenter, "alignVCenter");
    painter.drawText(rect, Qt::AlignBottom, "AlignBottom");
    painter.drawText(rect, Qt::AlignCenter, "AlignCenter");
    painter.drawText(rect, Qt::AlignBottom | Qt::AlignRight, "AlignBottom|AlignRight");
    painter.drawText(rect, Qt::AlignBottom | Qt::AlignCenter, "AlignBottom|AlignCenter");
    painter.drawText(rect, Qt::AlignCenter | Qt::AlignRight, "AlignCenter|AlignRight");
}
View Code

《QT Creator快速入门》第十章:2D绘制(3)第1张

使用QPainter::setFont()来设置文字字体,QPainter::fontInfo()可以获得当前字体信息,QFontDatabase类可以获得支持的所有字体族:

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    QFont font("宋体", 15, QFont::Bold, true); //字体族,磅值,字体粗细,是否斜体
    font.setUnderline(true);//设置下划线
    font.setCapitalization(QFont::AllUppercase);//设置字母大写
    font.setLetterSpacing(QFont::AbsoluteSpacing, 10);//设置字符间距
painter.setFont(font);
    painter.setPen(Qt::green);
    painter.drawText(120, 80, "yafei-linux");

    //平移并旋转后再绘制文本
    painter.translate(120, 100);
    painter.rotate(90);
    painter.drawText(0, 0, "hello qt");
}
View Code

《QT Creator快速入门》第十章:2D绘制(3)第2张

drawText()还有一个以一个点为基准来绘制文本的版本,如下所示,需要注意的是绘制的时候是以这个点的Y坐标为字体的baseline的:

《QT Creator快速入门》第十章:2D绘制(3)第3张

2、绘制图片

Qt提供了四个类来处理图像数据:QImage、QPixmap、QBitmap、QPicture。

①、QImage不仅可以加载一个图片然后显示出来,还可以在一个QImage上进行绘制文字,图形等操作,然后将这个QImage显示出来,如以下代码在QImage上进行一些绘制操作,然后显示出来:

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter;
    QImage image(100, 100, QImage::Format_ARGB32);

    painter.begin(&image);
    painter.setPen(QPen(Qt::green, 3));
    painter.setBrush(Qt::yellow);
    painter.drawRect(10, 10, 60, 60);
    painter.drawText(10, 10, 60, 60, Qt::AlignCenter, "QImage");
    painter.setBrush(QColor(0, 0, 0, 100));
    painter.drawRect(50, 50, 40, 40);
    painter.end();

    painter.begin(this);
    painter.drawImage(50, 20, image);
    painter.end();
}
View Code

《QT Creator快速入门》第十章:2D绘制(3)第4张

下面代码实现了加载图片然后显示,再将图片特殊处理后显示并另存为的功能:

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    QImage image;
    image.load("F://image.png");//加载图片
    qDebug() << "size: " << image.size() << "format: " << image.format() << "depth: " << image.depth();//获得图片信息
    painter.drawImage(10, 10, image);//显示图片
QImage mirror = image.mirrored();//获取图片镜像
QTransform transform;
    transform.shear(0.2, 0);
    QImage image2 = mirror.transformed(transform);//将图片扭曲
    painter.drawImage(300, 10, image2);//显示图片
    image2.save("F://image2.png");//保存图片
}
View Code

《QT Creator快速入门》第十章:2D绘制(3)第5张

QImage还提供了强大的访问和操作像素的功能。

②、一般是使用QPixmap加载和显示图像,如果需要提前对图像进行操作的话,先用QImage加载图片,对图片数据进行操作,然后将Qimage转换为QPixmap对象来显示图片(可以使用toImage()和fromImage()在QImage和QPixmap之间进行转换)。

QPixmap的fill()函数可以使用指定的颜色初始化整个pixmap图像,还可以使用grabWindows()和grabWidget()等静态函数来实现截取屏幕、截取窗口部件上内容功能。

以下代码使用QPixmap加载并显示了图片,并展示了在图片之上绘制一个透明矩形的效果:

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QPixmap pix;
    pix.load("./image.png");
    painter.drawPixmap(0, 0, pix);

    painter.drawPixmap(300, 0, pix);
    painter.setBrush(QColor(255, 255, 255, 100));
    painter.drawRect(300, 0, pix.width(), pix.height());

    painter.drawPixmap(0, 250, pix);
    painter.setBrush(QColor(0, 0, 255, 100));
    painter.drawRect(0, 250, pix.width(), pix.height());

    painter.drawPixmap(300, 250, pix);
    painter.setBrush(QColor(0, 0, 0, 150));
    painter.drawRect(300, 250, pix.width(), pix.height());
}
View Code

《QT Creator快速入门》第十章:2D绘制(3)第6张

drawPixmap()有很多重载函数,比如:

void QPainter::drawPixmap ( int x, int y, const QPixmap & pixmap ),表示使用pixmap中图片大小向(x, y)处绘制。

void QPainter::drawPixmap ( int x, int y, int width, int height, const QPixmap & pixmap ),表示向指定坐标和大小的位置绘制pixmap中内容

void QPainter::drawPixmap ( int x, int y, const QPixmap & pixmap, int sx, int sy, int sw, int sh ),表示向指定坐标绘制pixmap中指定位置和大小的内容。

下面的代码截取整个屏幕后保存文件,然后将截取的图像显示到一个Label上:

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(newUi::Widget)
{
    ui->setupUi(this);

    QPixmap screen = QPixmap::grabWindow(QApplication::desktop()->winId());
    screen.save("F://screen.png");

    QLabel* label = new QLabel(this);
    label->move(10, 10);

    label->resize(400, 200);
    QPixmap pix = screen.scaled(label->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
    label->setPixmap(pix);
}
View Code

《QT Creator快速入门》第十章:2D绘制(3)第7张

上面代码用到了QPixmap::scaled()函数,它可以对QPixmap上图像进行缩放后保存到另一个QPixmap对象上,其第一个参数指定缩放后的大小,第二个参数指定宽高比(Qt::IgnoreAspectRatio为自由缩放;Qt::KeepAspectRatio为保持宽高比,在给定的矩形内;Qt::KeepAspectRatioByExpanding为保持宽高比,在给定的矩形外;各选项效果见下图),第三个参数指定转换模式(快速转换Qt::FastTransformation和平滑转换Qt::SmoothTransformation) 。

《QT Creator快速入门》第十章:2D绘制(3)第8张

③、QBitmap只能用来处理和显示黑白两种颜色。

④、QPicture是一个可以记录和重演QPainter命令的绘图设备,即它可以将绘图命令序列化,对序列化的绘图命令进行重演。

⑤、使用QPainter::setCompositionMode()来设置绘图的复合模式,其中有QPainter::CompositionMode_SourceOver(默认模式)、QPainter::CompositionMode_DestinationOver等模式,各模式效果如下图:

《QT Creator快速入门》第十章:2D绘制(3)第9张

修改绘图的复合模式一个示例及效果:

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter;
    QImage image(400, 300, QImage::Format_ARGB32_Premultiplied);
    painter.begin(&image);

    painter.setBrush(Qt::red);
    painter.drawRect(100, 50, 200, 200);

    painter.setBrush(Qt::green);
    painter.drawRect(50, 0, 100, 100);

    painter.setBrush(Qt::blue);
    painter.setCompositionMode(QPainter::CompositionMode_DestinationOver);
    painter.drawRect(250, 0, 100, 100);

    painter.end();
    painter.begin(this);
    painter.drawImage(0, 0, image);
    painter.end();
}
View Code

《QT Creator快速入门》第十章:2D绘制(3)第10张

可以将图片添加到项目中来使用,添加图片资源的方法为:首先项目右键添加Qt资源文件(名称可以设置为myResource,路径为当前项目目录,点击确定后可以看到当前项目下有了一个qrc文件)->如果没有弹出资源编辑器页面的话右键点击qrc文件选择open in editor,然后点击下方的“添加”按钮,选择添加前缀,可以编辑前缀名为/image,按下ctrl+s保存->然后再点击下方的"添加"按钮,选择添加文件来添加图片文件(图片文件应该在qrc所在目录下或其子目录下),最后按下ctrl+s保存,然后在程序中就可以通过":/image/imageName.png"来使用图片:

void Widget::paintEvent(QPaintEvent*)
{
    QPainter painter(this);
    QPixmap pix(":/image/112.png");
    painter.drawPixmap(0, 0, pix);//在指定位置chu 原图大小显示
    //painter.drawPixmap(QRect(10, 10, 200, 160), pix,
    //QRect(0, 0, pix.width(), pix.height()));//按照指定区域缩放显示
}
View Code

3、其它图像处理类

QImageReader可以在加载图像时提供更多的控制,如使用setScaledSize()来将图像以指定的大小来读取,使用setClipRect()来只读取图像的一个区域。

QImageWriter提供了保存图像的更多控制,如压缩等级和品质、伽玛等级等。

QMovie可以用来播放gif动画,可以参考该类的帮助文档或查看Movie Player示例程序。

QSvgWidget可以加载一个SVG(可缩放矢量图形)文件,使用QSvgRenderer类在QSvgWidget中进行SVG文件的渲染,可以参考SVG Generator和SVG Viewer示例程序。

4、键盘事件鼠标事件、重绘事件

键盘按下事件处理函数:void keyPressEvent(QKeyEvent *);

键盘松开事件处理函数:void keyReleaseEvent(QKeyEvent *)

鼠标按下事件处理函数:mousePressEvent(QMouseEvent* event)
鼠标移动事件处理函数:mouseMoveEvent(QMouseEvent* event),如果想要保证不用按下鼠标也能触发鼠标移动事件,则在部件的构造函数中添加:setMouseTracking(true);
鼠标松开事件处理函数:mouseReleaseEvent(QMouseEvent* event)
鼠标滚轮滚动事件处理函数:wheelEvent(QWheelEvent *)
其中的QMouseEvent包含了鼠标信息,比如QMouseEvent::pos()可以获得当前鼠标位置。
重绘事件处理函数:void Widget::paintEvent(QPaintEvent *event)
重绘事件一般产生在repaint()或update()函数调用后,或者隐藏的部件被显示,或者其他一些原因。repaint()后paintEvent()会立即调用,update()会将重绘事件放入主消息循环中,如果update被调用了很多次,最后这些update会合并到一个大的重绘事件,所以只会调用一次update(),
一般情况下我们选择使用update()。
当重绘事件发生时,要更新的区域一般会被擦除,然后在部件的背景上进行绘制,部件的背景可以使用setBackgroundRole()函数来设置,然后使用setAutoFillBackground()函数来启用指定的颜色,eg:
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(newUi::Widget)
{
    ui->setupUi(this);
    
    ui->pushButton->setBackgroundRole(QPalette::Dark);
    ui->pushButton->setAutoFillBackground(true);
    
}
View Code

5、双缓冲

双缓冲绘图就是在绘制的时候将所有内容都绘制到一个绘图设备(如QPixmap)上,然后再将绘图设备中整个图像绘制到部件上显示出来,这样避免了一个一个的将内容绘制到部件上产生的显示闪烁现象。Qt4之后QWidget部件的所有绘制都自动使用了双缓冲,所以一般没必要在paintEvent()中使用双缓冲,不如如果想要实现一些绘图效果的话,还是要借助双缓冲的概念。

免责声明:文章转载自《《QT Creator快速入门》第十章:2D绘制(3)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇CentOS 6安装Oracle 11gR2数据库IDEA必备插件下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

[转]go语言中的接口

转,原文:  https://www.jianshu.com/p/82436645927b ------------------------------ 原文:https://medium.com/rungo/interfaces-in-go-ab1601159b3a 翻译:devabel 接口是golang中实现多态性的唯一好途径。 什么是接口? 我...

qt quick中qml编程语言

Qt QML 入门 — 使用C++定义QML类型 发表于2013 年 3 月 11 日 注册C++类 注册可实例化的类型 注册不实例化的QML类型 附带属性 注册C++类 注册可实例化的类型 如果一个C++类继承自QObject,如果需要在QML中使用创建对象,则需要注册为可实例化的QML类型。 使用qmlRegisterType()注册可...

【Ray Tracing The Next Week 超详解】 光线追踪2-7 任意长方体 &amp;amp;&amp;amp; 场景案例

上一篇比较简单,很久才发是因为做了一些好玩的场景,后来发现这一章是专门写场景例子的,所以就安排到了这一篇 Preface 这一篇要介绍的内容有: 1. 自己做的光照例子 2. Cornell box画质问题及优化方案 3. 新的场景几何体——长方体 轴平行长方体 任意长方体 我们这一篇重实践轻理论阐述 ready 1. 需要上一章的知识 但是,上一章的Co...

Java的各类型数据在内存中分配情况详解

1.      有这样一种说法,如今争锋于IT战场的两大势力,MS一族偏重于底层实现,Java一族偏重于系统架构。说法根据无从考证,但从两大势力各自的社区力量和图书市场已有佳作不难看出,此说法不虚,但掌握Java的底层实现对Java程序员来说是至关重要的,本文介绍了Java中的数据在内存中的存储。      2 内存中的堆(stack)与栈(heap) ...

IOS 之修改 Tabbar的背景颜色的几种方式:

1.在我们做项目的时候,我们经常会使用的要修改tabbar的背景颜色,有的是修改透明度,有的是替换背景颜色等等一其他的要求了,接下了有几种方法帮助你去修改对应的东西,如下所示: 第一张修改的是背景颜色:         UIImage *image = [UIImageimageNamed:@"tabbar.png"];         image = [...

SVG DOM常用属性和方法介绍

将以Adobe SVG Viewer提供的属性和方法为准,因为不同解析器对JavaScript以及相关的属性和方法支持的程度不同,有些方法和属性是某个解析器所特有的。SVG支持DOM2标准。 12.2.1 文档初始化相关evt属性evt表示事件本身,可以通过evt获取与当前事件相关的信息,用户可以在script中定义响应函数,进行相应的处理。它与普通Jav...