我有一个简单的QQuickPaintedItem,它在给定位置绘制了具有给定扇区大小和方位角的圆形扇区。这是标题:
#pragma once
#include <QtQuick/QQuickPaintedItem>
#include <QColor>
#include <QPainter>
class MarkerItem : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(QColor color READ color WRITE setColor)
Q_PROPERTY(int azimuth READ azimuth WRITE setAzimuth)
Q_PROPERTY(int sectorSize READ sectorSize WRITE setSectorSize)
Q_PROPERTY(QPointF anchorPoint READ anchorPoint WRITE setAnchorPoint NOTIFY anchorChanged)
Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectedChanged)
public:
MarkerItem(QQuickItem *parent = nullptr);
QColor color() const;
void setColor(const QColor &color);
int azimuth() const;
void setAzimuth(int angle);
int sectorSize() const;
void setSectorSize(int span);
QPointF anchorPoint() const;
void setAnchorPoint(const QPointF &value);
bool selected();
void setSelected(const bool bVal);
public slots:
void mousePressEvent(QMouseEvent *event) override;
protected:
void paint(QPainter *painter) override;
private:
QColor mcColor;
int miAzimuth;
int miSectorSize;
QPointF mcAnchorPoint;
bool mbSelected;
const int miSectorRadius = 40;
signals:
void anchorChanged(QPointF);
void selectedChanged(bool);
};
和实现:
#include "markeritem.h"
#include <QSGGeometryNode>
#include <QtMath>
MarkerItem::MarkerItem(QQuickItem *parent)
: QQuickPaintedItem(parent)
{
setAcceptedMouseButtons(Qt::LeftButton);
qDebug() << "MarkerItem";
setWidth(qTan(qDegreesToRadians(30.0f))*40);
setHeight(40);
mbSelected = false;
}
void MarkerItem::paint(QPainter *painter)
{
qDebug() << " > MarkerItem paint, azimuth " << miAzimuth;
QPen pen;
QBrush brush(mcColor);
if (mbSelected)
{
pen.setColor(Qt::magenta);
pen.setWidth(2);
brush.setColor(mcColor.lighter(150));
}
else
{
pen.setColor(Qt::black);
pen.setWidth(1);
}
painter->setPen(pen);
painter->setBrush(brush);
painter->setRenderHints(QPainter::Antialiasing, true);
const QRectF rect = boundingRect();
setAnchorPoint(QPointF(rect.left()+rect.width()/2.0,rect.bottom()));
// we define a helper rectangle what we use to draw a pie,
// as the drawPie() method expect a rect, and the pie will start from the
// center of that rect
QRectF cPieRect(anchorPoint().x()-rect.height(), anchorPoint().y()-rect.height(),
rect.height()*2,rect.height()*2);
painter->drawPie(cPieRect,(90-miSectorSize/2)*16, miSectorSize * 16);
// drawing the bounding rectangle in red for visual debugging
QPen pen2(Qt::red,1);
painter->setPen(pen2);
painter->setBrush(QBrush(Qt::transparent));
painter->drawRect(rect);
setTransformOriginPoint(anchorPoint());
setRotation(miAzimuth);
}
// setters/getters
QPointF MarkerItem::anchorPoint() const
{
return mcAnchorPoint;
}
void MarkerItem::setAnchorPoint(const QPointF &value)
{
mcAnchorPoint = value;
emit anchorChanged(value);
}
void
MarkerItem::mousePressEvent(QMouseEvent *event)
{
qDebug() << "MarkerItem MousePressEvent" << event;
setSelected(!mbSelected);
}
bool
MarkerItem::selected()
{
return mbSelected;
}
void
MarkerItem::setSelected(const bool bVal)
{
if (bVal == mbSelected)
{
return;
}
mbSelected = bVal;
emit selectedChanged(mbSelected);
update();
}
QColor MarkerItem::color() const
{
return mcColor;
}
void MarkerItem::setColor(const QColor &acColor)
{
mcColor = acColor;
}
int MarkerItem::azimuth() const
{
return miAzimuth;
}
void MarkerItem::setAzimuth(int angle)
{
miAzimuth = angle;
}
int MarkerItem::sectorSize() const
{
return miSectorSize;
}
void MarkerItem::setSectorSize(int angle)
{
miSectorSize = angle;
}
并像这样使用它:
import Marker 1.0 // this is the Markeritem class
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Item
{
id: root
visible: true
width: 1800
height: 900
MarkerItem
{
id: m0
x: 900
y:450
color: "green"
azimuth: 0
sectorSize: 30
}
MarkerItem
{
id: m1
x: 900
y:450
color: "green"
azimuth: 120
sectorSize: 30
}
}
QQuickPaintedItem定义一个适合绘制圆形部分的边界矩形,并使用QPainter的drawPie()方法绘制所需的形状,然后通过调用setRotate()将项目旋转到所需的方位角。我还需要处理鼠标单击事件以选择/取消选择一个项目。我的经验是,当某项的方位角为0(因此它没有旋转)时,边界矩形的鼠标事件被我的处理程序接收,但是当该项被旋转时,我的项却没有收到来自绘制项目的区域,但从边界矩形以外的区域接收一些鼠标事件,该区域似乎是原始区域的反射点,该区域的中心是锚点(如果是圆形扇形,则为尖端,这也是旋转的中心),但是很难定义将事件传递到我的处理程序的区域。 我的假设是通过“ setRotation()”调用,鼠标区域也在旋转。有什么我忽略的东西吗?有什么方法可以处理旋转项目中的鼠标事件?
应该通过MapQuickItem在地图项中使用该项目,但是如果没有地图项,该问题也可以重现,因此此处与地图相关的部分大部分都被省略了。
答案 0 :(得分:1)
setRotation()
旋转该项目,因此它不应处于绘制状态,因为每次绘制该项目时都会调用该方法,例如在鼠标事件之前,因此,setRotation()
仅应在{ {1}}
setAzimuth()
答案 1 :(得分:0)
好的,原来是问题出在不正确地设置变换原点上。我将锚点设置为边界矩形的底部中心为:
setTransformOriginPoint(anchorPoint());
锚点之前设置的位置
setAnchorPoint(QPointF(rect.center().x(),rect.bottom()));
如果我将转换原点显式设置为以下项的底部中心:
setTransformOrigin(QQuickItem::Bottom);
它可以正常工作。