f
fryn3May 8, 2018, 8:44 a.m.

Нарисовать дугу в QGraphicsItem

QGraphicsItem, Qt, QGraphicsScene

Необходимо уметь рисовать направленный граф.
В примерах QT нашел проект elasticnodes . Его переделал под свою задачу.
Получилось реализовать создание вершин/стрелок и их выделение/удаление/перемещение. Вот только не получается сделать дугу на самого себя и его область выделения.
Для выделение стрелок(Edge) подсмотрел реализацию области выделения в этой статье.
Помогите с реализацией дуги на себя.
Полностью проект выложен на гитхаб .
Пример реализации стрелки и дуги(некорректная дуга).
Edge::Edge(Node *sourceNode, Node *destNode)
    : id(_idStatic++), arrowSize(15)
{
    setFlag(QGraphicsItem::ItemIsSelectable);
    source = sourceNode;
    dest = destNode;
    source->addEdge(this);
    if(source != dest)
        dest->addEdge(this);
    adjust();
}

QPolygonF Edge::nPolygonMath() const {
    QPolygonF nPolygon;
    if (source != dest) {
        QLineF line = QLineF(sourcePoint.x(), sourcePoint.y(), destPoint.x(), destPoint.y());
        qreal radAngle = line.angle() * M_PI / 180;
        qreal selectionOffset = 3;
        qreal dx = selectionOffset * sin(radAngle);
        qreal dy = selectionOffset * cos(radAngle);
        QPointF offset1 = QPointF(dx, dy);
        QPointF offset2 = QPointF(-dx, -dy);
        nPolygon << line.p1() + offset1
                 << line.p1() + offset2
                 << line.p2() + offset2
                 << line.p2() + offset1;
    } else {
        nPolygon << mapFromItem(source, -Node::Radius, -Node::Radius)
                 << mapFromItem(source, Node::Radius, -Node::Radius)
                 << mapFromItem(source, Node::Radius, Node::Radius)
                 << mapFromItem(source, -Node::Radius, Node::Radius);
    }
    return nPolygon;
}

QRectF Edge::boundingRect() const
{
    if (!source || !dest)
        return QRectF();

    return nPolygonMath().boundingRect();

}

QPainterPath Edge::shape() const{
    QPainterPath ret;
    ret.addPolygon(nPolygonMath());
    return ret;
}

void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
    if (!source || !dest)
        return;

    painter->setPen(QPen((option->state & QStyle::State_Selected ? Qt::cyan: Qt::black), 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    if (source != dest) {
        QLineF line(sourcePoint, destPoint);
        if (qFuzzyCompare(line.length(), qreal(0.)))
            return;

        // Draw the line itself
        painter->drawLine(line);

        // Draw the arrows
        double angle = std::atan2(-line.dy(), line.dx());

        QPointF destArrowP1 = destPoint + QPointF(sin(angle - M_PI / 1.8) * qMin(arrowSize, line.length()),
                                                  cos(angle - M_PI / 1.8) * qMin(arrowSize, line.length()));
        QPointF destArrowP2 = destPoint + QPointF(sin(angle - M_PI + M_PI / 1.8) * qMin(arrowSize, line.length()),
                                                  cos(angle - M_PI + M_PI / 1.8) * qMin(arrowSize, line.length()));

        painter->setBrush((option->state & QStyle::State_Selected ? Qt::cyan: Qt::black));
        painter->drawPolygon(QPolygonF() << line.p2() << destArrowP1 << destArrowP2);
    } else {
        painter->drawArc(mapFromItem(source, Node::Radius, 0).x(),
                         mapFromItem(source, Node::Radius, 0).y(),
                         2 * Node::Radius, 2 * Node::Radius, 16 * -90, 16 * 180);

    }
}

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

1
Evgenii Legotckoi
  • May 17, 2018, 4:30 p.m.

Добрый день!

Оу, я смотрю по гитхабу, что вы уже разобрались с проблемой. Извиняюсь, заработался и забыл про ваш вопрос.

    Comments

    Only authorized users can post comments.
    Please, Log in or Sign up
    Lz

    C ++ - Test 004. Pointers, Arrays and Loops

    • Result:70points,
    • Rating points1
    РК

    Qt - Test 001. Signals and slots

    • Result:84points,
    • Rating points4
    Last comments
    d
    dblas5July 5, 2024, 9:02 p.m.
    QML - Lesson 016. SQLite database and the working with it in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
    k
    kmssrFeb. 9, 2024, 5:43 a.m.
    Qt Linux - Lesson 001. Autorun Qt application under Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
    Qt WinAPI - Lesson 007. Working with ICMP Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
    EVA
    EVADec. 25, 2023, 9:30 p.m.
    Boost - static linking in CMake project under Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
    J
    JonnyJoDec. 25, 2023, 7:38 p.m.
    Boost - static linking in CMake project under Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
    Now discuss on the forum
    BlinCT
    BlinCTJune 25, 2024, 11 a.m.
    Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
    Evgenii Legotckoi
    Evgenii LegotckoiJune 25, 2024, 1:11 a.m.
    добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
    BlinCT
    BlinCTMay 5, 2024, 3:46 p.m.
    Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
    Evgenii Legotckoi
    Evgenii LegotckoiMay 3, 2024, 12:07 a.m.
    Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.
    IscanderChe
    IscanderCheApril 30, 2024, 2:22 p.m.
    Во Flask рендер шаблона не передаётся в браузер Доброе утро! Имеется вот такой шаблон: <!doctype html><html> <head> <title>{{ title }}</title> <link rel="stylesheet" href="{{ url_…

    Follow us in social networks