拖动 QGraphicsItem 时的奇怪行为
Weird behaviour when dragging QGraphicsItem
我正在尝试在 Qt 中创建一个箭头项目,所以我以这个例子为基础:http://doc.qt.io/qt-5/qtwidgets-graphicsview-diagramscene-arrow-cpp.html
唯一的区别是我想将箭头连接到一个项目而不是两个。
一切正常,除了当我尝试拖动我的项目时,它会在后面留下一条模糊的痕迹,就好像它正在绘制整个拖动运动,如果我按 alt 键,它就会消失。
这是我拖动前的样子:
之后是:
只有箭头是这样的,我相信它的绘制事件可能有问题:
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
有什么提示吗?
问题是 MyArrow
的 boundingRect
仅以 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);
}
}
完整的解决方案可以在下面找到link
我正在尝试在 Qt 中创建一个箭头项目,所以我以这个例子为基础:http://doc.qt.io/qt-5/qtwidgets-graphicsview-diagramscene-arrow-cpp.html
唯一的区别是我想将箭头连接到一个项目而不是两个。 一切正常,除了当我尝试拖动我的项目时,它会在后面留下一条模糊的痕迹,就好像它正在绘制整个拖动运动,如果我按 alt 键,它就会消失。
这是我拖动前的样子:
之后是:
只有箭头是这样的,我相信它的绘制事件可能有问题:
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
有什么提示吗?
问题是 MyArrow
的 boundingRect
仅以 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);
}
}
完整的解决方案可以在下面找到link