0

I've found several similar questions pertaining to this topic, but haven't pieced together a workable solution as of yet. I've got non-rectangular Qt Quick Images, each with a child MouseArea. The current onClicked event registers clicks of the parent Image in areas of transparency, which I would like to ignore. Is there a QML-only solution to do this? Would a QML-only solution be adviseable, or should the transparency determination be done in c++?

Pseudocode in the main.qml file:

Image {
    id: testImage
    x: 200
    y: 100
    width: 100
    height: 150
    fillMode: Image.PreserveAspectFit
    source: "TestImage.svg"

    MouseArea {
        id: testMouseArea
        anchors.fill: parent
        onClicked: {
            //if alpha of (mouseX, mouseY) > 0 {
                //DO STUFF
            //}
        }
    }
}

My understanding is that getImageData() won't work for this purpose, so it may not be possible to determine the alpha level of the parent Image at the (mouseX, mouseY) coordinates in QML directly.

jars121
  • 1,127
  • 2
  • 20
  • 35
  • Please, have a look at Qt doc. [void QEvent::ignore()](http://doc.qt.io/qt-5/qevent.html#ignore). If I remember right, an ignored event is passed to the next potential receiver i.e. the next widget according to stacking order e.g. the parent widget. – Scheff's Cat Oct 29 '17 at 11:02
  • Do you have any real code, in which you tried some of the solutions on the web? One very promising solution can be found here: https://stackoverflow.com/questions/38164074/how-to-create-a-round-mouse-area-in-qml (i.e. second answer) – derM - not here for BOT dreams Oct 29 '17 at 11:03
  • I guess that's possible only by implementing custom `QQuickitem` iitem. – folibis Oct 29 '17 at 12:07

1 Answers1

1

You could use a QImage in C++ to enable querying the color of a pixel.

A short, very incomplete solution (just to outlay the idea) would be this:

*//MyMask.h

#ifndef MYMASK_H
#define MYMASK_H

#include <QObject>
#include <QImage>
#include <QString>

class MyMask : public QObject, public QImage
{
    Q_OBJECT
    Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
public:
    explicit MyMask(QObject *parent = nullptr);

    QString source() const;
    void setSource(const QString &source);

signals:
    void sourceChanged();
public slots:
    QColor color(int x, int y);

private:
    QString m_source;
};

#endif // MYMASK_H

// MyMask.cpp

#include "mymask.h"
#include <QRgb>
#include <QColor>
#include <QDebug>

MyMask::MyMask(QObject *parent)
    : QObject(parent),
      QImage()
{
    QObject::connect(this, &MyMask::sourceChanged, this, [this]() { QImage::load(m_source); });
}

QColor MyMask::color(int x, int y)
{
    return QImage::pixelColor(x, y);
}

QString MyMask::source() const
{
    return m_source;
}

void MyMask::setSource(const QString &source)
{
    if (source != m_source) {
        m_source = source;
        emit sourceChanged();
    }
}

It's probably wiser to use the QImage as a member rather than a base class but I started out as QImage until I realized, that it is no QObject.

As already mentioned, this is no complete implementation. For example it is not possible to adjust the size, e.g. to stretch it. Further you can't take Items as source and so on. There is also no control whether it is done with loading... But maybe this serves as a start for you.

You could even install it as a EventFilter to the Item that shall be clickable, to directly filter the MouseEvents for relevance.

  • 1
    Sorry for the delay in responding, I've only recently had a chance to address this issue. I've now got the solution working as required, thanks for your help! – jars121 Dec 07 '17 at 10:14
  • @jars121 do you have some sample for the working code? – puneet Jun 28 '21 at 14:31