使用QGraphicsItem绘制可缩放图片

Qt编辑图片组合一般是QPainter+QImage,但若是要实时显示往往不能直接随鼠标所在位置进行缩放,需要添加QScrollArea以及进行各种函数重写,接触到Qt中场景和图元概念后发现可以直接把图片作为一个图元,在场景中进行缩放对用户更友好,且不用写多余代码,废话不多说,直接上代码


Item.cpp

class ImageItemPrivate

{

public:

 

    ImageItemPrivate(int id,ImageItem * ptr);

    ~ImageItemPrivate();

 

    void draw(QPainter * p);

    QRectF sceneRect();

    bool savImage(QString fileName );

    // 宿主

    ImageItem * m_qPtr;

private:

    QImage m_image;//实际画布

    double m_dPicScale;//画布像素比 1cm-2pixel

    int m_id;

    QString m_title;

private:

    QColor penColor(int type);

    QBrush penBrush(int type);

    QFont textFont(int type);

    void buildImage();

};

ImageItemPrivate::ImageItemPrivate(int id,ImageItem * ptr) : m_qPtr(ptr)

{

    m_id = id;

    m_dPicScale = 2;//1cm-2pixel

    m_verlimit = 75;//75cm - 150pixel

    m_horlimit = 100;//100cm - 200pixel

    m_cenlimit = 80;//80cm - 160pix

    m_cubiclimit = 200;

 

    m_title = QString::number(id) + QStringLiteral("号图片信息") ;

 

    buildImage();

}

 

//实际位置转为图片位置 像素比:1cm-2pixel

QPolygonF ImageItemPrivate::scaleTrans(QPolygonF ply)

{

    QPolygonF polygon;

    foreach (QPointF pos, ply) {

       polygon.push_back(pos*m_dPicScale);

    }

    return polygon;

}

bool ImageItemPrivate::savImage(QString fileName)

{

//这里我初始直接用左下作为原点绘图,绘图结果当然不对,转图倒转就可以了;但后来又需要加文字等对方向敏感的图元就不行了,所以我又重新修改了各种数据直接以图片坐标系进行绘制,so sad.

//    QImage img = m_image.mirrored(false,true);

    return m_image.save(fileName);

}

//用于确定当前绘图大小,根据实际需求制定就好

QRectF ImageItemPrivate::sceneRect()

{

    double min_x,max_x;

    getCubiclesLimitSize(min_x,max_x);

 

    double dW = max_x;

    double dH = m_cubiclimit*2 + 2*m_verlimit + 2*m_cenlimit;

 

    return QRectF00, dW, dH );

}

//图片绘制事件

void ImageItemPrivate::draw(QPainter * p)

{

    if( !m_image.isNull() )

    {

        p->drawImage(m_qPtr->boundingRect(), m_image);

    }

}

void ImageItemPrivate::buildImage()

{

    int w =  sceneRect().width() * m_dPicScale;

    int h =  sceneRect().height() * m_dPicScale;

    m_image = QImage(w, h, QImage::Format_ARGB32);//图片确定宽和高

    m_image.fill(Qt::white);//默认白色画布

 

    QPainter p(&m_image);

    p.setRenderHint(QPainter::Antialiasing);//防锯齿

 

    //画外框线

p.setPen(QPen(penColor(ImageItem::IT_CUBICLESLINE), 2));

//使用scaleTrans统一完成实际位置和图片像素点位置转换

    p.drawPolygon(scaleTrans(m_cubicleLineF));//正面

    p.drawPolygon(scaleTrans(m_cubicleLineB));//背面

    p.drawPolygon(scaleTrans(m_cubicleLineT));//顶

    p.drawPolygon(scaleTrans(m_cubicleLineL));//左

p.drawPolygon(scaleTrans(m_cubicleLineR));//右

……

}

 

 

QRectF ImageItem::sceneRect()

{

    return m_dPtr->sceneRect();

}

 

bool ImageItem::savImage(QString fileName)

{

    return m_dPtr->savImage(fileName);

}

QPainterPath ImageItem::shape() const

{

    QPainterPath path;

    path.addRect(boundingRect());

    return path;

}

QRectF ImageItem::boundingRect() const

{

    QRectF sceneRct = m_dPtr->sceneRect();

    return QRectF(00, sceneRct.width(), sceneRct.height() );

}

void ImageItem::paintQPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)

{

    Q_UNUSED(option);

    Q_UNUSED(widget);

    m_dPtr->draw(painter);

}

 

Item.h

class ImageItemPrivate;

class ImageItem : public QObjectpublic QGraphicsItem

{

    Q_OBJECT

    Q_INTERFACES(QGraphicsItem)

public:

    enum ItemTypes{

        IT_CUBICLES = 0,

        IT_CUBICLESLINE,

        IT_LEGENDTEXT,

        IT_TITLETEXT,

        IT_UHF,

        IT_US,

        IT_CUBICLETEXT

    };//绘制图元类型,用于确定画笔,画刷颜色和字体属性

 

    ImageItem(int id);

~ImageItem();

//用于区分场景中图元类型以及图元转qgraphicsitem_cast()

    int type() const { return QGraphicsItem::UserType+14 ;}

    QRectF sceneRect();//可用于场景中坐标转换

    bool savImage(QString fileName );

    void paintQPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 );

    QPainterPath shape() const;

    QRectF boundingRect() const;

 

private:

    ImageItemPrivate * m_dPtr;

};

 

注意:

即使是不需要界面的控制台程序,当涉及桌面设置,风格,字体,调色板,光标等界面操作时,必须使用QApplication而非QCoreApplication!!

这里简直是一个大坑,在某个控制台小项目中用到了这个图元,想直接绘制并保存图片就好,结果一跑就崩!!

当初开发在windows系统,复用时在ubuntu系统,转了n圈找编码,系统字体,Qt版本,Ubuntu版本,编译器……最后发现QCoreApplication,想死……

因为当前图元涉及drawText,所以涉及到字体设置,而这些直接找帮助文档很难具体对应内容,发现之后再回头看倒是可以(然而有什么用呢TAT)经历分享给大家,望大家不要犯这种错误!

 

   

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
您可以重写QGraphicsItem的paint()方法,在其中使用QPainter绘制同心圆弧。 以下是一个简单的示例代码,它会在一个QGraphicsScene中绘制5个同心圆弧: ```cpp #include <QGraphicsItem> #include <QPainter> class ArcItem : public QGraphicsItem { public: ArcItem(qreal radius, qreal thickness, qreal startAngle, qreal spanAngle, QGraphicsItem *parent = nullptr) : QGraphicsItem(parent), m_radius(radius), m_thickness(thickness), m_startAngle(startAngle), m_spanAngle(spanAngle) {} QRectF boundingRect() const override { qreal penWidth = 1; return QRectF(-m_radius - m_thickness / 2 - penWidth / 2, -m_radius - m_thickness / 2 - penWidth / 2, 2 * (m_radius + m_thickness / 2 + penWidth / 2), 2 * (m_radius + m_thickness / 2 + penWidth / 2)); } void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override { painter->setRenderHint(QPainter::Antialiasing); QPen pen; pen.setWidthF(m_thickness); pen.setColor(QColor(0, 0, 255)); painter->setPen(pen); qreal startAngle = m_startAngle * 16; qreal spanAngle = m_spanAngle * 16; painter->drawArc(QRectF(-m_radius, -m_radius, 2 * m_radius, 2 * m_radius), startAngle, spanAngle); } private: qreal m_radius; qreal m_thickness; qreal m_startAngle; qreal m_spanAngle; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); QGraphicsScene scene; scene.setSceneRect(-200, -200, 400, 400); const int arcCount = 5; const qreal radiusStep = 40; const qreal thickness = 10; const qreal startAngle = 30; const qreal spanAngle = 120; for (int i = 0; i < arcCount; ++i) { qreal radius = (i + 1) * radiusStep; ArcItem *arc = new ArcItem(radius, thickness, startAngle, spanAngle); arc->setPos(0, 0); scene.addItem(arc); } QGraphicsView view(&scene); view.setRenderHint(QPainter::Antialiasing); view.show(); return app.exec(); } ``` 在这个示例中,我们定义了一个ArcItem类,继承自QGraphicsItem,它可以绘制一个同心圆弧。在paint()方法中,我们首先设置了绘制参数,然后使用QPainter的drawArc()方法绘制同心圆弧。在boundingRect()方法中,我们返回了绘制区域的矩形边界。 在main()函数中,我们创建了一个QGraphicsScene,并向其中添加了5个ArcItem对象,分别在不同的半径上绘制同心圆弧。最后,我们创建了一个QGraphicsView并显示了场景。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值