Andreas P
Andreas P

Reputation: 53

How to recieve Qt signal entered() in MouseArea from Touch?

I use MouseArea for buttons in my QT app and need to know, when the user moves his finger on the touch on a button. On W7 using a mouse, I get this information with onEntered from MouseArea.

The problem: on the target platform with touchscreen, the entered-signal is only fired, when I press the MouseArea (first touch inside MouseArea), then move my finger out (exited-signal), then move the finger back in (entered-signal). But when the first touch is outside the area and I enter it, entered-signal is not fired. I also tried MultiPointTouchArea with onTouchUpdated and onUpdated, same behaviour.

I am using Qt 5.5.1 on embedded linux.

Is there something I can do to make the MouseArea always fire the entered-signal? Or should I use something other than MouseArea or MultiPointTouchArea?

As a workaround I could think of a MouseArea on the complete window, with information where all the buttons are and checking on each positionChanged, if a button was entered, but I'm sure there must be a better solution.

Edit: When using a mouse on target platform, the entered-signal is fired when moving the mouse into the area.

This is my (simplified) code:

main.cpp

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QtQml>

#include "uart_terminal.h"

int main(int argc, char *argv[])
{
    system("mount /dev/mmcblk0p1 /mnt/sdcard/");
    setenv("QT_QPA_EGLFS_PHYSICAL_WIDTH", "376", 1);
    setenv("QT_QPA_EGLFS_PHYSICAL_HEIGHT", "301", 1);

    QApplication app(argc, argv);
    qmlRegisterType<UART_terminal>("com.uart", 1, 0, "UARTTerminal");

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("applicationDirPath", QGuiApplication::applicationDirPath());
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

main.qml:

    Window
    {
        id: rootWindow
        visible: true

        width: 1280
        height: 1024

        Rectangle
        {
            id: test
            color: "red"
            width: 300
            height: 300

            MouseArea
            {
                anchors.fill: parent

                hoverEnabled: true
                acceptedButtons: Qt.AllButtons

                onEntered:
                {
                    console.log("entered")
                    test.color = "blue"
                }
                onExited: test.color = "red"
                onCanceled: console.log("canceled")
                onPositionChanged:
                {
                    console.log("pos changed, containsMouse", containsMouse)
                }
            }

            /*MultiPointTouchArea
            {
                anchors.fill: parent
                onTouchUpdated: console.log("touch updated")
                onUpdated: console.log("touchlist updated")
            }*/
        }
    }

Upvotes: 2

Views: 1034

Answers (1)

Andreas P
Andreas P

Reputation: 53

So as I didn't find any other solution, I had to implement the mentioned work around. I put a MouseArea "buttonContainer" on the whole screen, behind all other MouseAreas. Note that I have to propagate the positionChanged signal from each MouseArea, otherwise it won't create my button-entered signal when I started the touch in one button and then enter another one.

onPositionChanged:
{
    // propagate event to buttonContainer with absolute mouse position
    var position = roundMouseArea.mapToItem(root)
    buttonContainer.xOffsetMouse = position.x
    buttonContainer.yOffsetMouse = position.y
    buttonContainer.positionChanged(mouse)
}

Then in buttonContainer's onPositionChanged I have to check for all Buttons that are currenty visible if they were entered. Don't forget to map each buttons position again with btn.mapToItem(buttonContainer) and to reset x- and yOffsetMouse in buttonContainer's onPressed.

In my case I had to do much more stuff like

  • check if button is disabled anyways, although visible
  • remember enteredBtn
  • set bool for each button if it's already entered from my container, so I don't get entered-signal at each positionChanged while I stay in that button
  • also check for button exited
  • set btnPressed true or false accordingly, eg. also at buttonContainer's onReleased
  • reset enteredBtn to undefined accordingly and check for that, before referencing any method or property of enteredBtn (eg. at buttonContainer's onReleased)

I think that was all. Don't want to copy my whole code here, just mention some aspects you might also need to consider if you have the same issue.

Upvotes: 0

Related Questions