C++实践之Qt学习(十):绘图

重绘事件

根据博客园这篇文章的介绍:

在Qt中,paintEvent方法是进行重绘的,只要出现以下几种情况,系统就会自动调用paintEvent方法。
a)当窗口部件第一次显示时,系统会自动产生一个绘图事件
b)重新调整窗口部件大小
c)当窗口部件被其他部件遮挡,然后又再次显示出来时,就会对隐藏的区域产生一个重绘事件

也可以通过调用QWidget::update()和QWidget::repaint()来产生一个绘图事件,其中repaint会强制产生一个即时的重绘事件,update会在Qt下一次处理事件时才会调用绘制事件,如果窗口部件在屏幕上是不可见的,则update和repaint什么都不会做。如果连续多次调用update方法,Qt会自动的将其压缩为一个单一的绘制事件,避免闪烁现象

因此,要实现绘图操作,就需要重写该函数,该函数不需要主动调用,也不需要关联到信号上,系统将会自动调用。

函数的原型:

[virtual protected] void QWidget::paintEvent(QPaintEvent *event)

绘制基本图形

在绘图事件中,可以通过QPainter画家类进行绘制操作。并可以给画家设置画笔QPen、画刷QBrush。

void GameWnd::paintEvent(QPaintEvent *event)
{
    QPainter painter(this); // 创建画家对象,并指定其绘图设备
    QPen pen(QColor(255, 102, 102)); // 创建画笔,可以指定绘图的线条颜色

    // 设置画笔宽度、风格
    pen.setWidth(5);
    pen.setStyle(Qt::DashDotLine);

    // 绘制直线
    painter.drawLine(0, 0, 100, 100);

    // 设置画家的画笔
    painter.setPen(pen);

    // 绘制矩形
    painter.drawRect(20, 20, 100, 80);

    QBrush brush(Qt::cyan); // 创建画刷,指定颜色,画刷的作用是绘制图形内部颜色
    brush.setStyle(Qt::Dense3Pattern); // 设置风格
    painter.setBrush(brush);

    // 绘制圆形
    painter.drawEllipse(QPoint(100, 100), 50, 50);

    // 绘制文字
    painter.drawText(10, 150, "这是一段文本内容");
    painter.drawText(QRect(10, 180, 100, 50), "这是一段文本内容");
}

还可以进行一些其他的操作,例如抗锯齿坐标系统移动还原

    // 设置抗锯齿
    painter.setRenderHint(QPainter::Antialiasing);

    painter.drawEllipse(QPoint(100, 200), 50, 50);

    // 保存画家状态
    painter.save();
    // 移动画家
    painter.translate(100, 0); // 坐标系横移了100

    painter.drawEllipse(QPoint(100, 200), 50, 50);

    // 还原状态
    painter.restore();

绘制资源图像

使用画家QPainterdrawPixmap函数可以绘制资源图片。该函数有多个重载:

void 
drawImage(const QRectF &target, const QImage &image, const QRectF &source, Qt::ImageConversionFlags flags = Qt::AutoColor)
void 
drawImage(const QRect &target, const QImage &image, const QRect &source, Qt::ImageConversionFlags flags = Qt::AutoColor)
void 
drawImage(const QPointF &point, const QImage &image, const QRectF &source, Qt::ImageConversionFlags flags = ...)
void 
drawImage(const QPoint &point, const QImage &image, const QRect &source, Qt::ImageConversionFlags flags = ...)
void 
drawImage(const QRectF &rectangle, const QImage &image)
void 
drawImage(const QRect &rectangle, const QImage &image)
void 
drawImage(const QPointF &point, const QImage &image)
void 
drawImage(const QPoint &point, const QImage &image)
void 
drawImage(int x, int y, const QImage &image, int sx = 0, int sy = 0, int sw = -1, int sh = -1, Qt::ImageConversionFlags flags = Qt::AutoColor)

可以实现多种绘制方式,并可以进行缩放绘制。

另外在绘制前可以先通过painter.translate,传入图片宽高一半,使坐标中心点移动到图片中心,然后再通过painter.rotate传入度数值进行旋转,就可以使图片中心旋转,绘制之后再通过painter.translate复原原点。

示例:滚动背景绘制

1)将背景图添加到资源文件中,并在代码中创建背景图对象

类声明中定义:

QPixmap *m_pBgPixmap; // 背景图资源

类实现中加载图片资源:

m_pBgPixmap = new QPixmap(":/imgs/bg");

2)在重绘定时器中调用repaint函数,触发重绘事件,并在重绘事件中调用绘制函数绘制滚动背景,为了记录滚动耗时,需要定义一个耗时计时器:

QElapsedTimer countScroll; // 记录时间间隔

在程序启动时启动计时定时器:

countScroll.start();

定义一个绘制背景图的函数,在重绘事件中调用:

void GameWnd::paintScene()
{
    int sw = m_pBgPixmap->width();
    int sh = m_pBgPixmap->height();
    int dw = this->width();
    int dh = this->height();

    static float scrollTime = 0.0f;
    scrollTime += countScroll.elapsed();
    countScroll.restart();
    if (scrollTime >= 20000)
    {
        scrollTime = 0.0f;
    }

    // 计算卷动高度
    int shScroll = (int)(scrollTime / 20000 * sh);
    //qDebug() << "卷动高度:" << shScroll;

    // 分两部分绘制
    QPainter painter(this);
    painter.drawPixmap(0, 0, dw, shScroll, *m_pBgPixmap, 0, sh - shScroll, sw, shScroll);
    painter.drawPixmap(0, shScroll, dw, dh - shScroll, *m_pBgPixmap, 0, 0, sw, sh - shScroll);
}
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值