QPainter

多些大家对我的支持啊!有朋友也提出,前面的几节有关event的教程缺少例子。因为event比较难做例子,也就没有去写,只是把大概写了一下。今天带来的是新的部分,有关Qt的2D绘图。这部分不像前面的内容,还是比较好理解的啦!所以,例子也会增加出来。
 
有人问豆子拿Qt做什么,其实,豆子就是在做一个Qt的画图程序,努力朝着Photoshop和GIMP的方向发展。但这终究要经过很长的时间、很困难的路程的,所以也放在网上开源,有兴趣的朋友可以来试试的呀…
 
好了,闲话少说,来继续我们的学习吧!
 
Qt的绘图系统允许使用相同的API在屏幕和打印设备上进行绘制。 整个绘图系统基于QPainter,QPainterDevice和QPaintEngine三个类。
 
QPainter用来执行绘制的操作;QPaintDevice是一个二维空间的抽象,这个二维空间可以由QPainter在上面进行绘制;QPaintEngine提供了画笔painter在不同的设备上进行绘制的统一的接口。QPaintEngine类用在QPainter和QPaintDevice之间,并且通常对开发人员是透明的,除非你需要自定义一个设备,这时候你就必须重新定义QPaintEngine了。
 
下图给出了这三个类之间的层次结构(出自Qt API 文档):
 
QPainter
 
这种实现的主要好处是,所有的绘制都遵循着同一种绘制流程,这样,添加可以很方便的添加新的特性,也可以为不支持的功能添加一个默认的实现方式。另外需要说明一点,Qt提供了一个独立的QtOpenGL模块,可以让你在Qt的应用程序中使用OpenGL功能。该模块提供了一个OpenGL的模块,可以像其他的Qt组件一样的使用。它的不同之处在于,它是使用OpenGL作为显示技术,使用OpenGL函数进行绘制。对于这个组件,我们以后会再介绍。
 
通过前面的介绍我们知道,Qt的绘图系统实际上是说,使用QPainter在QPainterDevice上面进行绘制它们之间使用QPaintEngine进行通讯。好了,下面我们来看看怎么使用QPainter。
 
首先我们定义一个组件,同前面的定义类似:
 
class PaintedWidget : public QWidget
{
public:
        PaintedWidget();

protected:
         void paintEvent(QPaintEvent * event);
};
这里我们只定义了一个构造函数,并且重定义paintEvent()函数。从名字就可以看出,这实际上是一个事件的回调函数。请注意,一般而言,Qt的事件函数都是protected的,所以,如果你要重写事件,就需要继承这个类了。至于事件相关的东西,我们在前面的内容已经比较详细的叙述了,这里不再赘述。
 
构造函数里面主要是一些大小之类的定义,这里不再详细说明:
 
PaintedWidget::PaintedWidget()
{
        resize(800, 600);
        setWindowTitle(tr( "Paint Demo"));
}
 
我们关心的是paintEvent()函数的实现:
 
void PaintedWidget::paintEvent(QPaintEvent * event)
{
        QPainter painter( this);
        painter.drawLine(80, 100, 650, 500);
        painter.setPen(Qt::red);
        painter.drawRect(10, 10, 100, 400);
        painter.setPen(QPen(Qt::green, 5));
        painter.setBrush(Qt::blue);
        painter.drawEllipse(50, 150, 400, 200);
}
 
为了把我们的程序运行起来,下面是main()函数:
 
int main( int argc, char *argv[])
{
        QApplication app(argc, argv);
        PaintedWidget w;
        w.show();
         return app.exec();
}
 
 
运行结果如下所示:
 
 
首先,我们声明了一个QPainter对象。注意,我们在这个函数的栈空间建立了对象,因此不需要delete。
 
QPainter接收一个QPaintDevice*类型的参数。QPaintDevice有很多子类,比如QImage,以及QWidget。注意回忆一下,QPaintDevice可以理解成要在哪里去画,而现在我们希望在这个widget上画,因此传入的是this指针。
 
QPainter有很多以draw开头的函数,用于各种图形的绘制,比如这里的drawLine,drawRect和和drawEllipse等。具体的参数请参阅API文档。下图给出了QPainter的draw函数的实例,本图来自C++ GUI Programming with Qt4, 2nd Edition.
 
 
好了,今天先到这里,我们将在下面一章中继续对这个paintEvent()函数进行说明。

本文出自 “豆子空间” 博客,请务必保留此出处http://devbean.blog.51cto.com/448512/235332

 
### QPainter 使用教程及解决方案 QPainterQt 框架中用于绘制 2D 图形的核心类之一,广泛应用于界面美化、图表绘制、动画制作等场景。通过 QPainter,开发者可以实现对窗口、图像、打印设备等目标的绘图操作。 #### 基本使用方法 QPainter 的使用通常围绕 `paintEvent()` 函数展开,这是 QWidget 的虚函数,用于响应重绘事件。基本流程如下: 1. 在自定义的控件中重写 `paintEvent(QPaintEvent *event)` 函数。 2. 在函数内部创建 QPainter 实例,并将其绑定到目标设备(如 QWidget)。 3. 使用 QPainter 提供的绘图函数进行图形绘制。 4. 绘制完成后,QPainter 实例自动销毁,或手动调用 `end()` 方法结束绘制。 示例代码如下: ```cpp void MyWidget::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); // 抗锯齿 painter.setPen(Qt::blue); painter.drawLine(0, 0, 100, 100); painter.setBrush(Qt::red); painter.drawRect(50, 50, 100, 100); } ``` #### 解决事件过滤器带来的困扰 在某些情况下,绘图操作可能受到事件过滤器的影响,例如控件被遮挡或布局变化时未正确触发重绘。为解决此类问题,可以通过手动调用 `update()` 或 `repaint()` 强制刷新控件。`update()` 将安排一次延迟绘制,而 `repaint()` 则立即触发重绘[^1]。 #### 使用 QPainter 与 OpenGL 的结合 虽然 QPainter 主要用于 2D 绘图,但在某些场景下需要与 OpenGL 配合使用,例如在 QGraphicsView 中绘制复杂的图形元素。需要注意的是,QPainter 并不支持某些 OpenGL 特性,例如 `QGraphicsPixmapItem` 在 OpenGL 上下文中无法直接绘制。此时可以考虑使用 QOpenGLFunctions 或其版本化变体(如 `QOpenGLFunctions_3_2_Core`)来确保跨平台兼容性[^2]。 #### 常见问题与解决方案 1. **绘图内容不显示**:确保在 `paintEvent()` 中正确创建 QPainter 实例,并检查是否调用了 `update()`。 2. **抗锯齿无效**:需调用 `setRenderHint(QPainter::Antialiasing)` 并确保目标设备支持该特性。 3. **与 OpenGL 混合使用失败**:避免直接调用 OpenGL 函数,改用 Qt 提供的封装类如 `QOpenGLFunctions`。 4. **QGraphicsItem 中绘图异常**:避免在 `paint()` 方法中直接清空颜色缓冲区,应通过 Qt 的绘图机制管理。 #### 高级技巧 - **离线绘图**:可以将绘图操作绘制到 QImage 或 QPixmap 上,实现离线渲染后再显示。 - **路径绘制**:使用 `QPainterPath` 可以构建复杂的路径并进行绘制,适用于矢量图形。 - **渐变与纹理**:结合 `QLinearGradient`、`QRadialGradient` 和 `QPixmap` 实现丰富的视觉效果。 ```cpp QPixmap pixmap(200, 200); pixmap.fill(Qt::white); QPainter p(&pixmap); p.setBrush(Qt::blue); p.drawEllipse(50, 50, 100, 100); ``` #### 总结 QPainterQt 中强大的 2D 绘图工具,通过合理使用其 API,可以实现丰富的图形界面效果。同时,开发者需注意与事件机制、OpenGL 交互等细节,以确保应用的稳定性和跨平台兼容性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值