首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >QGraphicsScene中的弧

QGraphicsScene中的弧
EN

Stack Overflow用户
提问于 2014-11-13 04:48:41
回答 2查看 10.1K关注 0票数 2

我想在QGraphicsScene中实现弧。我希望在点击三点时,我的弧线应该被画出来,在点击三点时,画出第一个点是弧线的起点,第二个点是弧线上的任意点,第三个点是弧的终点。我曾试过研究drawArc函数,但却把它弄糊涂了。我无法动态地设置它们。请建议我怎么做。

我尝试将该解决方案添加到我的项目中,但得到了以下错误:

代码语言:javascript
运行
复制
error: cannot allocate an object of abstract type 'arc'
                 arcItem = new arc(++id, startP, midP, endP);

你能帮我解决这个问题吗?我为我的项目提供了一部分代码。在按摩器事件中,我做了下面的事情。

cadgraphicsscene.cpp

代码语言:javascript
运行
复制
    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

代码语言:javascript
运行
复制
#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

代码语言:javascript
运行
复制
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

请帮我解决这个错误。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-11-14 20:10:24

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

注意: Qt包含更高级的子类QGraphicsItem示例,例如碰撞鼠标,以及40000个芯片示例。

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

另外,要启用来自QObjectQGraphicsItem信号、插槽和属性,您应该使用QGraphicsObject

注意:添加到github 这里中。

arcgraphicsitem.h

代码语言:javascript
运行
复制
#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

代码语言:javascript
运行
复制
#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;
}

希望这有帮助

票数 3
EN

Stack Overflow用户

发布于 2014-11-13 07:36:06

这听起来似乎可以用一些相对简单的数学来解决:

https://www.google.com/search?q=define%20circle%20three%20points

https://math.stackexchange.com/a/213678

二分/v/三点-定义-a-圆

这是我把数学转化为Qt善良的地方

代码语言:javascript
运行
复制
// m_points is a QList<QPointF>
// use math to define the circle
QLineF lineBC(m_points.at(1), m_points.at(2));
QLineF lineAC(m_points.at(0), m_points.at(2));
QLineF lineBA(m_points.at(1), m_points.at(0));
qreal rad = qAbs(lineBC.length()/(2*qSin(qDegreesToRadians(lineAC.angleTo(lineBA)))));

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

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

QPointF center;
bisectorBA.intersect(bisectorBC, &center);

qDebug() << rad << center;

QT QGraphicsScene绘图弧

代码语言:javascript
运行
复制
QPainterPath* path = new QPainterPath();
path->arcMoveTo(0,0,50,50,20);
path->arcTo(0,0,50,50,20, 90);
scene.addPath(*path);

把所有这些放在一个很好的小项目中,就会变成这样:

https://github.com/peteristhegreat/ThreePointsCircle

main.cpp

代码语言:javascript
运行
复制
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

mainwindow.h

代码语言:javascript
运行
复制
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
};

#endif // MAINWINDOW_H

mainwindow.cpp

代码语言:javascript
运行
复制
#include "mainwindow.h"
#include <QGraphicsView>
#include <QGraphicsScene>
#include "graphicsscene.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QGraphicsView * view = new QGraphicsView;

    GraphicsScene * scene = new GraphicsScene();
    view->setScene(scene);

    view->setSceneRect(-300,-300, 300, 300);
    this->resize(600, 600);

    this->setCentralWidget(view);
}

MainWindow::~MainWindow()
{

}

graphicsscene.h

代码语言:javascript
运行
复制
#ifndef GRAPHICSSCENE_H
#define GRAPHICSSCENE_H

#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QPointF>
#include <QList>

class GraphicsScene : public QGraphicsScene
{
    Q_OBJECT
public:
    explicit GraphicsScene(QObject *parent = 0);
    virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent * mouseEvent);
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * mouseEvent);
    virtual void mousePressEvent(QGraphicsSceneMouseEvent * mouseEvent);
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * mouseEvent);
signals:

public slots:

private:
    QList <QPointF> m_points;
};

#endif // GRAPHICSSCENE_H

graphicsscene.cpp

代码语言:javascript
运行
复制
#include "graphicsscene.h"
#include <QDebug>
#include <QGraphicsEllipseItem>
#include <QGraphicsPathItem>
#include <QPainterPath>
#include "qmath.h"

GraphicsScene::GraphicsScene(QObject *parent) :
    QGraphicsScene(parent)
{
    this->setBackgroundBrush(Qt::gray);
}

void GraphicsScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * mouseEvent)
{
    qDebug() << Q_FUNC_INFO << mouseEvent->scenePos();
    QGraphicsScene::mouseDoubleClickEvent(mouseEvent);
}

void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent * mouseEvent)
{
    qDebug() << Q_FUNC_INFO << mouseEvent->scenePos();
    QGraphicsScene::mouseMoveEvent(mouseEvent);
}

void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent * mouseEvent)
{
    qDebug() << Q_FUNC_INFO << mouseEvent->scenePos();
    QGraphicsScene::mousePressEvent(mouseEvent);
}

void GraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent * me)
{
    qDebug() << Q_FUNC_INFO << me->scenePos();
    int radius = 20;
    QGraphicsEllipseItem * ellipse = this->addEllipse(me->scenePos().x() - radius, me->scenePos().y() - radius, radius*2, radius*2);

    ellipse->setBrush(Qt::white);
    m_points.append(me->scenePos());
    if(m_points.size() == 3)
    {
        // use math to define the circle
        QLineF lineBC(m_points.at(1), m_points.at(2));
        QLineF lineAC(m_points.at(0), m_points.at(2));
        QLineF lineBA(m_points.at(1), m_points.at(0));
        qreal rad = qAbs(lineBC.length()/(2*qSin(qDegreesToRadians(lineAC.angleTo(lineBA)))));

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

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

        QPointF center;
        bisectorBA.intersect(bisectorBC, &center);

        qDebug() << rad << center;

        bool drawCircle = true;

        QGraphicsEllipseItem * ellipse = new QGraphicsEllipseItem(center.x() - rad, center.y() - rad, rad*2, rad*2);
        if(drawCircle)
            this->addItem(ellipse);

        // add arc
        // this->addItem(path);
        QPainterPath path;
        QLineF lineOA(center, m_points.at(0));
        QLineF lineOC(center, m_points.at(2));
        path.arcMoveTo(ellipse->boundingRect(),lineOA.angle());
        path.arcTo(ellipse->boundingRect(), lineOA.angle(), lineOC.angle() - lineOA.angle());
        QGraphicsPathItem * pathItem = new QGraphicsPathItem(path);
        pathItem->setPen(QPen(Qt::red,10));
        this->addItem(pathItem);

        if(!drawCircle)
            delete ellipse;
        m_points.clear();
    }

    QGraphicsScene::mouseReleaseEvent(me);
}
票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26901540

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档