Странное поведение при перетаскивании QGraphicsItem - PullRequest
0 голосов
/ 05 июня 2018

Я пытаюсь создать элемент стрелки в Qt, поэтому я опираюсь на этот пример: http://doc.qt.io/qt-5/qtwidgets-graphicsview-diagramscene-arrow-cpp.html

Единственное отличие состоит в том, что я хочу подключить стрелку к одному элементу, а недва.И все это работает, за исключением того, что когда я пытаюсь перетащить свой элемент, он оставляет размытый след позади, как если бы он рисовал все движение при перетаскивании, и если я нажимаю Alt Tab, он исчезает.

Перед перетаскиванием: enter image description here

И вот после: enter image description here

Так ведет себя только стрелка, и я считаю, что с еесобытие рисования:

void myArrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){

qreal arrowSize = 20;
double angle = std::atan2(-line().dy(), line().dx());

QPointF arrowP1 = line().p1() + QPointF(sin(angle + M_PI / 3) * arrowSize,
                                cos(angle + M_PI / 3) * arrowSize);
QPointF arrowP2 = line().p1() + QPointF(sin(angle + M_PI - M_PI / 3) * arrowSize,
                                cos(angle + M_PI - M_PI / 3) * arrowSize);

arrowHead.clear();
arrowHead << line().p1() << arrowP1 << arrowP2;

painter->drawLine(line());
painter->drawPolygon(arrowHead);
}

Если я уберу наконечник стрелки, удалив эту строку painter->drawPolygon(arrowHead), то сама линия работает нормально.

Вот весь исходный проект: https://github.com/Matheusih/0000000123

Любые подсказки, пожалуйста?

1 Ответ

0 голосов
/ 05 июня 2018

Проблема в том, что boundingRect из MyArrow принимает только QLineF в качестве основы, а не стрелку, которая генерирует этот нежелательный эффект.

Мое решение предлагает использовать QGraphicsPathItemвместо QGraphicsLineItem, кроме того, я не понимаю вашу логику, реализованную в moveLineToCenter, я считаю ее ненужной, я изменил ее, чтобы обновить ее положение:

myarrow.h

#ifndef MYARROW_H
#define MYARROW_H

class CustomRect;

#include <QGraphicsPathItem>

class MyArrow : public QGraphicsPathItem
{
public:
    MyArrow(CustomRect *rect);
    void updatePosition(QPointF p1, QPointF p2);
private:
    CustomRect *myrect;
};

#endif // MYARROW_H

myarrow.cpp

#include "customrect.h"
#include "myarrow.h"

#include <QPainter>

#include <cmath>

MyArrow::MyArrow(CustomRect *rect){
    myrect = rect;
    QPointF p = rect->boundingRect().center();
    updatePosition(p - QPointF(0, 50), p - QPointF(0, 250));
    setFlag(QGraphicsLineItem::ItemIsSelectable);
}

void MyArrow::updatePosition(QPointF p1, QPointF p2)
{

    const qreal arrowSize = 20;

    QPainterPath path;

    path.moveTo(p1);
    path.lineTo(p2);

    QPointF diff = p2-p1;
    double angle = std::atan2(-diff.y(), diff.x());

    QPointF arrowP1 = p1 + QPointF(sin(angle + M_PI / 3) * arrowSize,
                                    cos(angle + M_PI / 3) * arrowSize);
    QPointF arrowP2 = p1 + QPointF(sin(angle + M_PI - M_PI / 3) * arrowSize,
                                    cos(angle + M_PI - M_PI / 3) * arrowSize);
    QPolygonF arrowHead;
    arrowHead << p1 << arrowP1 << arrowP2 << p1;
    path.moveTo(p1);
    path.addPolygon(arrowHead);

    setPath(path);
}

customrect.h

#ifndef CUSTOMRECT_H
#define CUSTOMRECT_H

#include <QGraphicsPixmapItem>

class MyArrow;

class CustomRect : public QGraphicsRectItem
{
public:
    CustomRect (const QRectF& rect);
    void addLine(MyArrow *line);
    QVariant itemChange(GraphicsItemChange change, const QVariant &value);

    void moveLineToCenter(QPointF newPos);

private:
    QList<MyArrow *> arrows;
};
#endif // CUSTOMRECT_H

customrect.cpp

#include "customrect.h"
#include "myarrow.h"

CustomRect::CustomRect(const QRectF &rect) : QGraphicsRectItem(rect){
    setFlag(QGraphicsItem::ItemIsMovable);
    setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
}

void CustomRect::addLine(MyArrow *line) {
    arrows << line;
}

QVariant CustomRect::itemChange(GraphicsItemChange change, const QVariant &value)
{
    if (change == ItemPositionChange && scene()) {
        QPointF newPos = value.toPointF();
        moveLineToCenter(newPos);
    }
    return QGraphicsItem::itemChange(change, value);
}

void CustomRect::moveLineToCenter(QPointF newPos) {

    for(MyArrow *arrow: arrows) {
        arrow->setPos(newPos);
    }
}

Полное решение можно найти по следующей ссылке

...