Hi all,
I’m going insane with a strange behaviour in iOS. I create a custom QQuickItem based on the MaskedMouseArea from the examples.
It works perfectly with Android and Desktop. But when I click on my component in iOS I get only the message:
“stale focus object QQuickloader…” and nothing happens. I can see from the logs that the component constructor in c++ was called and I get no other
message that something is wrong. But after the stale message no mouse event is triggered.
#ifndef MASKEDMOUSEAREA_H
#define MASKEDMOUSEAREA_H
#include <QImage>
#include <QQuickItem>
#include <QQmlEngine>
class MaskedMouseArea : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(bool pressed READ isPressed NOTIFY pressedChanged)
Q_PROPERTY(bool containsMouse READ containsMouse NOTIFY containsMouseChanged)
Q_PROPERTY(QUrl maskSource READ maskSource WRITE setMaskSource NOTIFY maskSourceChanged)
Q_PROPERTY(qreal alphaThreshold READ alphaThreshold WRITE setAlphaThreshold NOTIFY alphaThresholdChanged)
public:
MaskedMouseArea(QQuickItem *parent = 0);
Q_INVOKABLE void scaleToSized(int width, int height);
bool contains(const QPointF &point) const;
bool isPressed() const { return m_pressed; }
bool containsMouse() const { return m_containsMouse; }
QUrl maskSource() const { return m_maskSource; }
void setMaskSource(const QUrl &source);
qreal alphaThreshold() const { return m_alphaThreshold; }
void setAlphaThreshold(qreal threshold);
signals:
void pressed();
void released();
void clicked();
void canceled();
void pressedChanged();
void maskSourceChanged();
void containsMouseChanged();
void alphaThresholdChanged();
protected:
void setPressed(bool pressed);
void setContainsMouse(bool containsMouse);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void hoverEnterEvent(QHoverEvent *event);
void hoverLeaveEvent(QHoverEvent *event);
void mouseUngrabEvent();
private:
bool m_pressed;
QUrl m_maskSource;
QImage m_maskImage;
QPointF m_pressPoint;
qreal m_alphaThreshold;
bool m_containsMouse;
};
#endif
#include "maskedmousearea.h"
#include <QStyleHints>
#include <QGuiApplication>
#include <qqmlfile.h>
#include <QDebug>
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::scaleToSized(int width, int height){
m_maskImage = m_maskImage.scaledToWidth(width);
// m_maskImage = m_maskImage.scaledToHeight(height);
qDebug() << "target Size: " << m_maskImage.width();
}
void MaskedMouseArea::setMaskSource(const QUrl &source)
{
if (m_maskSource != source) {
m_maskSource = source;
m_maskImage = QImage(QQmlFile::urlToLocalFileOrQrc(source));
qDebug() << "target Width: " << width();
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;
// } else {
// qDebug() << " in image";
// }
if (p.x() < 0 || p.x() >= width() ||
p.y() < 0 || p.y() >= height()){
return false;
} else {
// qDebug() << " in image";
}
qreal r = qBound<int>(0, m_alphaThreshold * 255, 255);
// if (qAlpha(m_maskImage.pixel(p)) > r)
// qDebug() << "inside";
return qAlpha(m_maskImage.pixel(p)) > r;
}
void MaskedMouseArea::mousePressEvent(QMouseEvent *event)
{
qDebug() << "mouse" ;
setPressed(true);
m_pressPoint = event->pos();
event->setAccepted(false);
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();
event->setAccepted(false);
}
void MaskedMouseArea::mouseUngrabEvent()
{
setPressed(false);
emit canceled();
}
void MaskedMouseArea::hoverEnterEvent(QHoverEvent *event)
{
Q_UNUSED(event);
setContainsMouse(true);
event->setAccepted(false);
}
void MaskedMouseArea::hoverLeaveEvent(QHoverEvent *event)
{
Q_UNUSED(event);
setContainsMouse(false);
event->setAccepted(false);
}
qmlRegisterType<MaskedMouseArea>("com.pxx.pd", 1,0, "MaskedMouseArea");
AppImage {
id: mainImage
property string sourceImage
property string region
anchors.fill: parent
fillMode: Image.PreserveAspectFit
smooth: true
source: sourceImage
MaskedMouseArea {
id: imageMask
anchors.fill: parent
alphaThreshold: 0.8
maskSource: sourceImage
onPressed: {
showRegion(parent, mainImage.region)
}
Component.onCompleted: {
scaleToSized(width, height)
}
}
Behavior on scale {
NumberAnimation { duration: 400 }
}
}
As I said it works on the other plattforms. So is there anything else I have to do on iOS?
Thx,
patrik