QGraphicsScene中的圆弧 [英] Arc in QGraphicsScene

查看:103
本文介绍了QGraphicsScene中的圆弧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 QGraphicsScene 中实现 arc.我希望在点击三个点时我的弧应该被绘制,这样在点击三个点时就会绘制弧,其中第一个点将是弧的起点,第二个将是弧上的任何点,第三个将是弧的终点.我曾尝试研究 drawArc 函数,但对 startangle 和 spanangle 感到困惑.我无法动态设置它们.请给我建议一些方法来继续.

I want to implement arc in QGraphicsScene. I want that on clicking of three points my arc should be drawn such that on clicking of three points arc is drawn where first point will be starting of arc, second will be any point on arc and third will be end point of arc. I have tried studing drawArc function but got confused with startangle and spanangle. I was unable to set them dynamically. Please suggest me some way to proceed.

我尝试将解决方案嵌入到我的项目中,但出现以下错误:

I tried the solution to embend it in my project but got the following error:

error: cannot allocate an object of abstract type 'arc'
                 arcItem = new arc(++id, startP, midP, endP);

你能帮我解决这个问题吗?我正在为我的项目提供一部分代码.在cadgraphicsscene的mousepress事件中,我做了以下事情.

Can you please help me out to solve the problem. I am giving a part of code to my project. In mousepress event of cadgraphicsscene I have done following thing.

cadgraphicsscene.cpp

cadgraphicsscene.cpp

    void CadGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
    {
        // mousePressEvent in the graphicsScene
        if(mouseEvent->button() == Qt::LeftButton)
        {
            switch (entityMode)
            {

            case ArcMode:
                if (mFirstClick)
                {
                    startP = mouseEvent->scenePos();
                    mFirstClick = false;
                    mSecondClick = true;
                }

                else if (!mFirstClick && mSecondClick)
                {
                    midP = mouseEvent->scenePos();
                    mFirstClick = false;
                    mSecondClick = false;
                    mThirdClick = true;
                }

                else if (!mSecondClick && mThirdClick)
                {
                    endP = mouseEvent->scenePos();
                    mThirdClick = false;
                    mPaintFlag = true;
                }

                if (mPaintFlag)
                {
                    arcItem = new arc(++id, startP, midP, endP);
                    itemList.append(arcItem);
                    mUndoStack->push(new CadCommandAdd(this, arcItem));
                    setFlags();
                }
            }
        }
   } 

arc.cpp

#include "arc.h"

arc::arc(int i, QPointF point1, QPointF point2, QPointF point3)
{
    // assigns id
    id = i;
    p1 = point1;
    p2 = point2;
    p3 = point3;

    lineBC(point2, point3);
    lineAC(point1, point3);
    lineBA(point2, point1);

    rad = qAbs(lineBC.length()/(2*qSin(qDegreesToRadians(lineAC.angleTo(lineBA)))));

    bisectorBC(lineBC.pointAt(0.5), lineBC.p2());
    bisectorBC.setAngle(lineBC.normalVector().angle());

    bisectorBA(lineBA.pointAt(0.5), lineBA.p2());
    bisectorBA.setAngle(lineBA.normalVector().angle());


    bisectorBA.intersect(bisectorBC, &center);

    ellipse = new QGraphicsEllipseItem(center.x() - rad, center.y() - rad, rad*2, rad*2);

    lineOA(center, point1);
    lineOC(center, point3);
}

arc::arc(int i, QLineF start, QLineF end)
{
    // assigns id
    id = i;

    lineOA.angle() = start;
    lineOC.angle() - lineOA.angle() = end;
}

int arc::type() const
{
    // Enable the use of qgraphicsitem_cast with arc item.
    return Type;
}

void arc::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                QWidget *widget)
{
    QPen paintpen;
    painter->setRenderHint(QPainter::Antialiasing);
    paintpen.setWidth(1);

    if (isSelected())
    {
        // sets brush for end points
        painter->setBrush(Qt::SolidPattern);
        paintpen.setColor(Qt::red);
        painter->setPen(paintpen);

        paintpen.setStyle(Qt::DashLine);
        paintpen.setColor(Qt::black);
        painter->setPen(paintpen);
        painter->drawArc(ellipse->boundingRect(),lineOA.angle(),lineOC.angle() - lineOA.angle());
    }
    else
    {
        painter->setBrush(Qt::SolidPattern);
        paintpen.setColor(Qt::black);
        painter->setPen(paintpen);
        painter->drawArc(ellipse->boundingRect(),lineOA.angle(),lineOC.angle() - lineOA.angle());

    }
}

arc.h

include <QGraphicsItem>

#include "qmath.h"
class arc : public QObject, public QGraphicsItem
{
    Q_OBJECT
public:
    arc(int, QPointF, QPointF, QPointF);
    arc(int, QLineF, QLineF);


    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                       QWidget *widget);
    enum { Type = UserType + 6 };
    int type() const;
    int id;

    QPointF startP, midP, endP, p1, p2, p3,center;
    QLineF lineBC;
    QLineF lineAC;
    QLineF lineBA;
    QLineF lineOA;
    QLineF lineOC;
    QLineF bisectorBC;
    QLineF bisectorBA;
    QGraphicsEllipseItem *ellipse;
    qreal rad;

private:
    QVector<QPointF> stuff;

};

#endif // ARC_H

请帮我解决这个错误.

推荐答案

QGraphicsItem 的一个子类,取 3 个点,并用圆弧与三个点相交.第二点总是在中间.(可选性和其他属性尚未完全实现或测试).

A Subclass of QGraphicsItem, that takes 3 points, and intersects the three with an arc of a circle. The second point is always in the middle. (Selectablity and other properties haven't been fully implemented or tested).

注意:Qt Creator 包含更高级的子类 QGraphicsItem 示例,例如 Colliding Mice 和 40,000 个筹码示例.

Note: Qt Creator includes more advanced examples of subclassed QGraphicsItems such as Colliding Mice, and 40,000 chips examples.

http://qt-project.org/doc/qt-5/examples-graphicsview.html

还要从 QGraphicsItem 启用 QObject 信号和槽以及属性,您应该使用 QGraphicsObject.

Also to enable QObject signals and slots and properties from a QGraphicsItem, you should use QGraphicsObject.

注意:添加到 github 此处.

Note: added onto github here.

arcgraphicsitem.h

arcgraphicsitem.h

#ifndef ARCGRAPHICSITEM_H
#define ARCGRAPHICSITEM_H

#include <QGraphicsItem>
#include <QLineF>
#include <QPointF>
#include <QPainter>
#include <QStyleOptionGraphicsItem>
#include <QWidget>

class ArcGraphicsItem : public QGraphicsItem
{

public:
    ArcGraphicsItem();
    ArcGraphicsItem(int i, QPointF point0, QPointF point1, QPointF point2);
    ~ArcGraphicsItem();

    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

    int type() const { return Type;}
    int id() {return m_id;}

    QPainterPath shape() const;
protected:

private:
    void init();

    enum { Type = UserType + 6 };
    int m_id;

    QPointF startP, midP, endP, p1, p2, p3, center;
    QLineF lineBC;
    QLineF lineAC;
    QLineF lineBA;
    QLineF lineOA;
    QLineF lineOB;
    QLineF lineOC;
    QLineF bisectorBC;
    QLineF bisectorBA;
    qreal startAngle;
    qreal spanAngle;

    QRectF circle;
    QRectF boundingRectTemp;
    qreal rad;
};

#endif // ARCGRAPHICSITEM_H

arcgraphicsitem.cpp

arcgraphicsitem.cpp

#include "arcgraphicsitem.h"
#include "qmath.h"
#include <QPen>
#include <QDebug>
#include <QPainterPath>

ArcGraphicsItem::ArcGraphicsItem(int i,
                                 QPointF point1,
                                 QPointF point2,
                                 QPointF point3)
    : m_id(i), p1(point1), p2(point2), p3(point3)

{
    init();
}


ArcGraphicsItem::ArcGraphicsItem()
{
    p1 = QPointF(0,0);
    p2 = QPointF(0,1);
    p3 = QPointF(1,1);
    m_id = -1;
    init();
}

ArcGraphicsItem::~ArcGraphicsItem()
{

}

void ArcGraphicsItem::init()
{
    lineBC = QLineF(p2, p3);
    lineAC = QLineF(p1, p3);
    lineBA = QLineF(p2, p1);

    rad = qAbs(lineBC.length()/(2*qSin(qDegreesToRadians(lineAC.angleTo(lineBA)))));

    bisectorBC = QLineF(lineBC.pointAt(0.5), lineBC.p2());
    bisectorBC.setAngle(lineBC.normalVector().angle());

    bisectorBA = QLineF(lineBA.pointAt(0.5), lineBA.p2());
    bisectorBA.setAngle(lineBA.normalVector().angle());
    bisectorBA.intersect(bisectorBC, &center);

    circle = QRectF(center.x() - rad, center.y() - rad, rad*2, rad*2);

    lineOA = QLineF(center, p1);
    lineOB = QLineF(center, p2);
    lineOC = QLineF(center, p3);


    startAngle = lineOA.angle();
    spanAngle = lineOA.angleTo(lineOC);
    // Make sure that the span angle covers all three points with the second point in the middle
    if(qAbs(spanAngle) < qAbs(lineOA.angleTo(lineOB)) || qAbs(spanAngle) < qAbs(lineOB.angleTo(lineOC)))
    {
        // swap the end point and invert the spanAngle
        startAngle = lineOC.angle();
        spanAngle = 360 - spanAngle;
    }

    int w = 10;
    boundingRectTemp = circle.adjusted(-w, -w, w, w);
}

QRectF ArcGraphicsItem::boundingRect() const
{
    // outer most edges
    return boundingRectTemp;
}

void ArcGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QPen paintpen;
    painter->setRenderHint(QPainter::Antialiasing);
    paintpen.setWidth(1);
    // Draw arc

    if(isSelected())
    {
        painter->setBrush(Qt::SolidPattern);
        paintpen.setColor(Qt::black);
        painter->setPen(paintpen);
    }
    else
    {
        paintpen.setStyle(Qt::DashLine);
        paintpen.setColor(Qt::black);
        painter->setPen(paintpen);
    }

    QPainterPath path;
    path.arcMoveTo(circle,startAngle);
    path.arcTo(circle, startAngle, spanAngle);

    // Draw points

    if (isSelected())
    {
        // sets brush for end points
        painter->setBrush(Qt::SolidPattern);
        paintpen.setColor(Qt::red);
        painter->setPen(paintpen);

        qreal ptRad = 10;
        painter->drawEllipse(p1, ptRad, ptRad);
        painter->drawEllipse(p2, ptRad, ptRad);
        painter->drawEllipse(p3, ptRad, ptRad);
    }

    painter->setBrush(Qt::NoBrush);
    painter->drawPath(path);
}

QPainterPath ArcGraphicsItem::shape() const
{
    QPainterPath path;
    path.arcMoveTo(circle,startAngle);
    path.arcTo(circle, startAngle, spanAngle);
    return path;
}

希望有帮助

这篇关于QGraphicsScene中的圆弧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆