Skip to content

Instantly share code, notes, and snippets.

@mitchcurtis
Last active June 18, 2021 08:23
Show Gist options
  • Save mitchcurtis/50193c73a8d1fd9e5955193a3983d840 to your computer and use it in GitHub Desktop.
Save mitchcurtis/50193c73a8d1fd9e5955193a3983d840 to your computer and use it in GitHub Desktop.
QQuickItem that handles hover events and has a custom "cursor"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QLoggingCategory>
#include <QDebug>
#include <QQuickItem>
#include <QQuickWindow>
Q_LOGGING_CATEGORY(lcEvents, "hover.events")
class EventItem : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(int cursorX READ cursorX NOTIFY cursorXChanged)
Q_PROPERTY(int cursorY READ cursorY NOTIFY cursorYChanged)
public:
EventItem() {
setAcceptedMouseButtons(Qt::AllButtons);
setAcceptHoverEvents(true);
}
int cursorX() const
{
return mCursorX;
}
void setCursorX(int cursorX)
{
if (cursorX == mCursorX)
return;
mCursorX = cursorX;
emit cursorXChanged();
}
int cursorY() const
{
return mCursorY;
}
void setCursorY(int cursorY)
{
if (cursorY == mCursorY)
return;
mCursorY = cursorY;
emit cursorYChanged();
}
signals:
void cursorXChanged();
void cursorYChanged();
protected:
void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &/*data*/) override
{
if (change == QQuickItem::ItemSceneChange && window())
window()->setCursor(QCursor(Qt::BlankCursor));
}
void mousePressEvent(QMouseEvent *event) override
{
qCDebug(lcEvents) << "mousePressEvent -" << event;
QQuickItem::mousePressEvent(event);
updateCursorPos(event->pos());
event->accept();
}
void mouseMoveEvent(QMouseEvent *event) override
{
qCDebug(lcEvents) << "mouseMoveEvent -" << event;
QQuickItem::mouseMoveEvent(event);
updateCursorPos(event->pos());
}
void mouseReleaseEvent(QMouseEvent *event) override
{
qCDebug(lcEvents) << "mouseReleaseEvent -" << event;
QQuickItem::mouseReleaseEvent(event);
updateCursorPos(event->pos());
}
void hoverEnterEvent(QHoverEvent *event) override
{
qCDebug(lcEvents) << "hoverEnterEvent:" << event;
QQuickItem::hoverEnterEvent(event);
updateCursorPos(event->position().toPoint());
}
void hoverMoveEvent(QHoverEvent *event) override
{
qCDebug(lcEvents) << "hoverMoveEvent:" << event->position();
QQuickItem::hoverMoveEvent(event);
updateCursorPos(event->position().toPoint());
}
void hoverLeaveEvent(QHoverEvent *event) override
{
qCDebug(lcEvents) << "hoverLeaveEvent:" << event;
QQuickItem::hoverLeaveEvent(event);
}
private:
void updateCursorPos(const QPoint &eventPos)
{
qCDebug(lcEvents).nospace() << "updating cursor pos to " << eventPos << "...";
setCursorX(eventPos.x());
setCursorY(eventPos.y());
}
// The position of the cursor in view coordinates.
int mCursorX = -1;
int mCursorY = -1;
};
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
qmlRegisterType<EventItem>("App", 1, 0, "EventItem");
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
#include "main.moc"
import QtQuick 2.15
import QtQuick.Window 2.15
import App 1.0
Window {
width: 640
height: 480
visible: true
title: "cursorX: " + eventItem.cursorX + " cursorY: " + eventItem.cursorY
EventItem {
id: eventItem
anchors.fill: parent
Rectangle {
x: eventItem.cursorX - width / 2
y: eventItem.cursorY - height / 2
width: 2
height: 2
color: "black"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment