【问题标题】:How can I use a MouseArea on a ShapePath in QML?如何在 QML 中的 ShapePath 上使用 MouseArea?
【发布时间】:2020-07-24 10:06:03
【问题描述】:

我目前正在学习如何使用 QML 中的 Shapes 来绘制更高级的组件。我正在尝试创建一个如下所示的按钮:

当我尝试在 Shape 组件上应用 MouseArea 时,MouseArea 似乎无法捕获 Shape 上的事件。这是我的代码:

import QtQuick 2.13
import QtQuick.Shapes 1.13

Item
{
    Shape
    {
        id: myShape

        ShapePath {
            id: myButton

            strokeWidth:3.114000082015991
            strokeColor: "#000"
            miterLimit:7
            fillColor: "#ccc"
            capStyle:ShapePath.RoundCap
            PathSvg {
                path: "M392.4,205.9a132.34,132.34,0,0,1,31.7,49.2H575.6a289.67,289.67,0,0,0-12.9-49.2Z"
            }
        }
    }

    MouseArea
    {
        id: myMouseArea
        anchors.fill: myShape
        enabled: true
        hoverEnabled: true

        onEntered: myButton.fillColor = "yellow"
        onExited: myButton.fillColor = "green"
    }
}

所以我的问题是:是否可以首先使 Shape/ShapePath 可点击?如果是,该怎么做?

【问题讨论】:

    标签: qt qml shapes mousearea


    【解决方案1】:

    here 提出了类似的问题,但他们只想要一个简单的圆圈。尽管如此,不接受的答案描述了一个可能对您有用的蒙面鼠标区域。它使用图像来定义蒙版区域。它最初来自一个 Qt example program

    ma​​skedmousearea.cpp

    MaskedMouseArea::MaskedMouseArea(QQuickItem *parent)
        : QQuickItem(parent),
          m_pressed(false),
          m_alphaThreshold(0.0),
          m_containsMouse(false)
    {
        setAcceptHoverEvents(true);
        setAcceptedMouseButtons(Qt::LeftButton);
    }
    
    void MaskedMouseArea::setPressed(bool pressed)
    {
        if (m_pressed != pressed) {
        m_pressed = pressed;
        emit pressedChanged();
        }
    }
    
    void MaskedMouseArea::setContainsMouse(bool containsMouse)
    {
        if (m_containsMouse != containsMouse) {
        m_containsMouse = containsMouse;
        emit containsMouseChanged();
        }
    }
    
    void MaskedMouseArea::setMaskSource(const QUrl &source)
    {
        if (m_maskSource != source) {
        m_maskSource = source;
        m_maskImage = QImage(QQmlFile::urlToLocalFileOrQrc(source));
        emit maskSourceChanged();
        }
    }
    
    void MaskedMouseArea::setAlphaThreshold(qreal threshold)
    {
        if (m_alphaThreshold != threshold) {
        m_alphaThreshold = threshold;
        emit alphaThresholdChanged();
        }
    }
    
    bool MaskedMouseArea::contains(const QPointF &point) const
    {
        if (!QQuickItem::contains(point) || m_maskImage.isNull())
        return false;
    
        QPoint p = point.toPoint();
    
        if (p.x() < 0 || p.x() >= m_maskImage.width() ||
        p.y() < 0 || p.y() >= m_maskImage.height())
        return false;
    
        qreal r = qBound<int>(0, m_alphaThreshold * 255, 255);
        return qAlpha(m_maskImage.pixel(p)) > r;
    }
    
    void MaskedMouseArea::mousePressEvent(QMouseEvent *event)
    {
        setPressed(true);
        m_pressPoint = event->pos();
        emit pressed();
    }
    
    void MaskedMouseArea::mouseReleaseEvent(QMouseEvent *event)
    {
        setPressed(false);
        emit released();
    
        const int threshold = qApp->styleHints()->startDragDistance();
        const bool isClick = (threshold >= qAbs(event->x() - m_pressPoint.x()) &&
                          threshold >= qAbs(event->y() - m_pressPoint.y()));
    
        if (isClick)
        emit clicked();
    }
    
    void MaskedMouseArea::mouseUngrabEvent()
    {
        setPressed(false);
        emit canceled();
    }
    
    void MaskedMouseArea::hoverEnterEvent(QHoverEvent *event)
    {
        Q_UNUSED(event);
        setContainsMouse(true);
    }
    
    void MaskedMouseArea::hoverLeaveEvent(QHoverEvent *event)
    {
        Q_UNUSED(event);
        setContainsMouse(false);
    }
    

    在 QML 中的使用:

    import Example 1.0
    MaskedMouseArea {
        id: moonArea
        anchors.fill: parent
        alphaThreshold: 0.4
        maskSource: moon.source
    }
    

    注册自定义项:

    qmlRegisterType<MaskedMouseArea>("Example", 1, 0, "MaskedMouseArea");
    

    【讨论】:

      猜你喜欢
      • 2021-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-10
      相关资源
      最近更新 更多