Как я могу использовать MouseArea на ShapePath в QML?
В настоящее время я изучаю, как использовать фигуры в QML для рисования более сложных компонентов. Я пытаюсь создать кнопку, которая выглядит так:
Когда я пытаюсь применить MouseArea к компоненту Shape, 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 интерактивным? И если да, то как это сделать?
1 ответ
Аналогичный вопрос был задан здесь, но они просто хотели простой круг. Тем не менее, непринятый ответ описывает замаскированную область мыши, которая может быть вам полезна. Он использует изображение для определения замаскированной области. Первоначально он взят из примера программы Qt.
maskedmousearea.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");