实现可移动,可拉大或者缩小,并且选定后,有虚线外框的三角形。以下是实现三角形类的代码:
TriangleItem.h:
#ifndef TRIANGLEITEM_H
#define TRIANGLEITEM_H
#include <QGraphicsPolygonItem>
class TriangleItem : public QGraphicsPolygonItem
{
public:
enum ResizeMode {
None,
Zoom,
};
explicit TriangleItem(QGraphicsItem* parent = nullptr);
protected:
void hoverMoveEvent(QGraphicsSceneHoverEvent* event) override;
void hoverLeaveEvent(QGraphicsSceneHoverEvent* event) override;
void mousePressEvent(QGraphicsSceneMouseEvent* event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent* event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override;
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
private:
bool isNearVertex(const QPointF& pos);
void updateBoundingRect();
bool m_isSelected;
int m_nearestVertexIndex;
QPointF m_mousePressOffset;
ResizeMode m_resizeMode;
};
#endif // TRIANGLEITEM_H
TriangleItem.cpp:
#include "TriangleItem.h"
#include <QDebug>
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QStyleOptionGraphicsItem>
TriangleItem::TriangleItem(QGraphicsItem* parent)
: QGraphicsPolygonItem(parent)
{
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
setAcceptHoverEvents(true);
QPolygonF polygon;
polygon << QPointF(0, 0) << QPointF(50, 100) << QPointF(100, 0);
setPolygon(polygon);
setPen(Qt::DashLine);
m_isSelected = false;
m_resizeMode = None;
}
void TriangleItem::hoverMoveEvent(QGraphicsSceneHoverEvent* event)
{
QPointF pos = event->pos();
if (isNearVertex(pos)) {
setCursor(QCursor(Qt::SizeFDiagCursor));
} else {
setCursor(QCursor(Qt::ArrowCursor));
}
}
void TriangleItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
{
Q_UNUSED(event)
setCursor(Qt::ArrowCursor);
}
void TriangleItem::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
m_isSelected = true;
setSelected(true);
if (event->button() == Qt::LeftButton) {
QPointF pos = event->pos();
if (isNearVertex(pos)) {
QList<QPointF> vertices = polygon().toList();
qreal minDistance = QLineF(vertices[0], pos).length();
int nearestVertexIndex = 0;
for (int i = 1; i < vertices.size(); ++i) {
qreal distance = QLineF(vertices[i], pos).length();
if (distance < minDistance) {
minDistance = distance;
nearestVertexIndex = i;
}
}
m_nearestVertexIndex = nearestVertexIndex;
m_mousePressOffset = vertices[m_nearestVertexIndex] - pos;
if (nearestVertexIndex == 0 || nearestVertexIndex == 2) {
m_resizeMode = Zoom;
setCursor(QCursor(Qt::SizeVerCursor));
} else if (nearestVertexIndex == 1) {
m_resizeMode = Zoom;
setCursor(QCursor(Qt::SizeHorCursor));
} else {
m_resizeMode = None;
setCursor(QCursor(Qt::ArrowCursor));
}
} else {
setCursor(QCursor(Qt::ArrowCursor));
QGraphicsPolygonItem::mousePressEvent(event);
}
}
}
void TriangleItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
if (m_resizeMode == Zoom) {
QPointF pos = event->pos();
QPolygonF polygon = this->polygon();
polygon[m_nearestVertexIndex] = pos + m_mousePressOffset;
setPolygon(polygon);
setCursor(QCursor(Qt::SizeFDiagCursor));
updateBoundingRect();
} else {
QGraphicsPolygonItem::mouseMoveEvent(event);
}
}
void TriangleItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
if (event->button() == Qt::LeftButton) {
m_isSelected = false;
updateBoundingRect();
setCursor(QCursor(Qt::ArrowCursor));
m_resizeMode = None;
}
QGraphicsPolygonItem::mouseReleaseEvent(event);
}
void TriangleItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
Q_UNUSED(widget)
QBrush brush(Qt::white);
painter->setBrush(brush);
painter->drawPolygon(polygon());
if (m_isSelected && option->state & QStyle::State_Selected) {
QPen pen(Qt::DashLine);
painter->setPen(pen);
painter->setBrush(Qt::NoBrush);
painter->drawRect(boundingRect());
}
}
void TriangleItem::updateBoundingRect()
{
if (m_isSelected) {
setPen(QPen(Qt::DashLine));
} else {
setPen(Qt::NoPen);
}
}
bool TriangleItem::isNearVertex(const QPointF& pos)
{
QList<QPointF> vertices = polygon().toList();
for (const QPointF& vertex : vertices) {
if (QLineF(vertex, pos).length() < 10) {
return true;
}
}
return false;
}
本文暂时没有评论,来添加一个吧(●'◡'●)