二十三、绘图框架设计

二十三、绘图框架设计QPainter

QPainter 提供高度优化的特征来做大多数的 GUI 程序绘制要求。它可以绘制从简单直线到复杂形状的一切。它还可以绘制对齐文本和像素图。通常,它在自然坐标系中绘制,但也可以在视图和世界坐标系之间变换。QPainter 可以操作的任何对象继承 QPaintDevice 类。

常见 QPainter 用法是在小部件描绘事件内:构造和定制 (如:设置钢笔或笔刷) 描绘器。然后绘制。记得销毁 QPainter 对象在绘制后。

QPainter 类的核心功能是绘制,但还提供允许定制 QPainter 设置、渲染品质及其它使能够裁剪的一些功能。另外,通过指定描绘器的合成模式可以控制如何将不同形状合并在一起。

isActive () 函数指示描绘器是否活动。激活描绘器通过 begin () 函数且构造函数接受 QPaintDevice 自变量。 end () 函数,和析构函数将其取消激活。

连同 QPaintDevice and QPaintEngine 类,QPainter 形成用于 Qt 描绘系统的基。QPainter 是用于履行绘制操作的类。 QPaintDevice 表示可以使用 QPainter 进行描绘的设备。 QPaintEngine 提供用于在不同类型设备上描绘的描绘器接口。若描绘器活动, device () 返回描绘器在其上描绘的描绘设备,和 paintEngine () 返回描绘器目前正在操作的描绘引擎。更多信息,见 描绘系统 .

有时,可能期望其它人去描绘在不寻常 QPaintDevice 。QPainter 支持静态函数 setRedirected() 来做这。

警告: 当 paintdevice 是 Widget 时,QPainter 只可用于 paintEvent() 函数内或调用 paintEvent() 的函数内。

 完成以下功能

选择Line绘画出直线,选择Rectangle绘画出矩形。

首先我们创建一个QWidget工程

然后再创建一个源文件和头文件,叫painterpro,该文件继承QWidget。

painterpro.h

#ifndef PAINTERPRO_H
#define PAINTERPRO_H

#include <QWidget>

#include<QPen> //笔
#include<QBrush> //画刷
#include<QPainter>

class painterpro : public QWidget
{
    Q_OBJECT
public:
    explicit painterpro(QWidget *parent = nullptr);

    //绘画直线,长方形
    enum shape{line,rectangle};

    void setShape(shape);
    void setPen(QPen);
    void setBrush(QBrush);

    void paintEvent(QPaintEvent *);
    void setFillRule(Qt::FillRule);


signals:

private:
    shape shp;
    QPen pen;
    QBrush brush;
    Qt::FillRule fillRule;

};

#endif // PAINTERPRO_H

painterpro.cpp

#include "painterpro.h"

painterpro::painterpro(QWidget *parent) : QWidget(parent)
{
    setPalette(QPalette(Qt::red));
    setAutoFillBackground(true);

    setMinimumSize(410,410);
}

void painterpro::setShape(shape sh)
{
    shp=sh;
    update();
}

void painterpro::setPen(QPen pe)
{
    pen=pe;
    update();
}

void painterpro::setBrush(QBrush br)
{
    brush=br;
    update();
}

void painterpro::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    p.setPen(pen);
    p.setBrush(brush);

    QRect rect(55,110,290,180);

    switch(shp)
    {
    case line:
        p.drawLine(rect.topLeft(),rect.bottomRight());
        break;
    case rectangle:
        p.drawRect(rect);
        break;
    default:
        break;
    }
}

void painterpro::setFillRule(Qt::FillRule fr)
{
    fillRule=fr;
    update();
}

void QWidget::update():

更新小部件,除非禁用更新或小部件被隐藏。
此函数不会导致立即重绘;相反,当Qt返回到主事件循环时,它调度一个绘画事件进行处理。这允许Qt优化更快的速度和更少的闪烁,而不是调用repaint()。
多次调用update()通常只会导致一次paintEvent()调用。

Qt通常在paintEvent()调用之前擦除小部件的区域。如果设置了Qt::WA_OpaquePaintEvent小部件属性,则小部件负责用不透明的颜色绘制其所有像素。

void QPainter::drawLine(const QLineF &line):

绘制由线定义的线。

QPoint QRect::topLeft() const:

返回矩形左上角的位置。

QPoint QRect::bottomRight() const:

返回矩形右下角的位置。
注意,由于历史原因,这个函数返回QPoint(left() + width() -1, top() + height() -1)。

void QPainter::drawRect(const QRectF &rectangle):

使用当前笔和画笔绘制当前矩形。
填充矩形的大小为rectangle.size()。描边矩形的大小为rectangle.size()加上笔的宽度。

enum Qt::FillRule:

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

#include"painterpro.h"
#include<QLabel>
#include<QComboBox>
#include<QGridLayout>
#include<QColorDialog>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;

    painterpro *ppro;
    QLabel *labelShape;
    QComboBox *comboboxShape;
    QGridLayout *gl;

private slots:
    void shapeFunc(int);
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

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

    ppro=new painterpro;
    gl=new QGridLayout;

    labelShape=new QLabel("绘制形状");
    comboboxShape=new QComboBox();
    comboboxShape->addItem("Line",painterpro::line);
    comboboxShape->addItem("Rectangle",painterpro::rectangle);

    connect(comboboxShape,SIGNAL(activated(int)),this,SLOT(shapeFunc(int)));

    gl->addWidget(labelShape,0,0);
    gl->addWidget(comboboxShape,0,1);

    QHBoxLayout *hbl=new QHBoxLayout(this);
    hbl->addWidget(ppro);
    hbl->addLayout(gl);

}

Widget::~Widget()
{
    delete ui;
}

void Widget::shapeFunc(int v)
{
    painterpro::shape sp=painterpro::shape(comboboxShape->itemData(v,Qt::UserRole).toInt());
    ppro->setShape(sp);
}


void activated(int index):

当索引处的项目被用户激活时,就会发出这个信号。
当一个项目在弹出窗口打开时被选中,导致弹出窗口关闭(并且currentIndex改变),或者当弹出窗口关闭并且组合框通过键盘导航时,导致currentIndex改变时,该项目被激活。设置currentIndex属性为index。

QVariant QComboBox::itemData(int index, int role = Qt::UserRole) const:

返回组合框中给定索引中给定角色的数据,如果没有此角色的数据,则返回QVariant::无效。

enum Qt::ItemDataRole:

该项目的整体逻辑并不难,我们只需要先在painterpro文件中完成我们所需求的主要功能即可,然后在widget文件中进行项目部件的布局,调用painterpro文件中的功能。

主要是重载的paintEvent函数和信号与槽函数,信号被触发后,槽函数进行调用,这时会调用setShape函数,当update函数调用时,就会重新自动调用绘制事件,然后进行绘图的更新。

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Mo Yan

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

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

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

打赏作者

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

抵扣说明:

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

余额充值