程序员的知识教程库

网站首页 > 教程分享 正文

使用QT生成新的三角形的类,可移动、可伸缩的三角形

henian88 2024-08-13 06:15:43 教程分享 8 ℃ 0 评论

实现可移动,可拉大或者缩小,并且选定后,有虚线外框的三角形。以下是实现三角形类的代码:

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;
}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表