3

I am new in Qt. I am working on windows desktop application and using Qt with qml. On PC that hasn't QTouchDevices, splitter between component (element that allow you resize component on window) works good with mouse (screenshot "Good distance"), but if screen is touchscreen I have next problem, please look on screenshot "Wrong distance".

My application shouldn't support any touch device. So how to disable this Qt feature? I need the same behavior like on device without touch screen.

Wrong distance

Wrong distance

Good distance

Good distance

I have tried disable touch device using privet methods using next sample:

QWindowSystemInterface::unregisterTouchDevice(QTouchDevice::devices().first());

This works, but QWindowSystemInterface is private class and it disable touchscreen. And one more in QTCreator splitters work fine, exactly as I need.

vard
  • 4,057
  • 2
  • 26
  • 46
Victor.V
  • 177
  • 1
  • 9

2 Answers2

1

If you can't patch Qt, the only way that I can think of would be to iterate through the children, searching for the MouseArea. For example, suppose you had this QML:

import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.1

ApplicationWindow {
    width: 600
    height: 400
    visible: true

    property alias splitView: splitView

    SplitView {
        id: splitView
        anchors.fill: parent

        Rectangle {
            width: 200
            Layout.maximumWidth: 400
            color: "lightblue"
            Text {
                text: "View 1"
                anchors.centerIn: parent
            }
        }

        Rectangle {
            id: centerItem
            Layout.minimumWidth: 50
            Layout.fillWidth: true
            color: "lightgray"
            Text {
                text: "View 2"
                anchors.centerIn: parent
            }
        }
    }
}

You could then print out the object tree of the SplitView like so:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickItem>
#include <QDebug>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    QObject *window = engine.rootObjects().first();
    QQuickItem *splitView = window->property("splitView").value<QQuickItem*>();
    splitView->dumpObjectTree();

    return app.exec();
}

That gives you:

SplitView_QMLTYPE_1:: 
    QQmlComponent:: 
    QQuickSystemPalette:: 
    QObject_QML_2:: 
    QQmlComponent:: 
    QQuickItem:: 
    QQuickItem:: 
    QQuickItem:: 
        QQuickLoader_QML_3:: 
            QObject_QML_4:: 
            QQuickMouseArea_QML_5:: 
            QQuickRectangle:: 
                QQmlContext:: 
    QQuickItem:: 
    QQmlComponentAttached:: 
    QQuickRectangle:: 
        QQuickText:: 
        QQuickLayoutAttached:: 
    QQuickRectangle:: 
        QQuickText:: 
        QQuickLayoutAttached:: 
    QQuickLayoutAttached:: 

QObject::dumpObjectTree() prints out metaObject->className(), so we know to look for an object whose metaObject has a className matching that:

Then:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickItem>
#include <QScreen>
#include <QWindow>
#include <QDebug>

QQuickItem *findMouseArea(QQuickItem *item)
{
    foreach (QQuickItem *childItem, item->childItems()) {
        if (QString(childItem->metaObject()->className()).startsWith(QStringLiteral("QQuickMouseArea_QML"))) {
            return childItem;
        } else {
            QQuickItem *mouseArea = findMouseArea(childItem);
            if (mouseArea) {
                return mouseArea;
            }
        }
    }

    return 0;
}

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    QWindow *window = qobject_cast<QWindow*>(engine.rootObjects().first());
    QQuickItem *splitView = window->property("splitView").value<QQuickItem*>();
    QQuickItem *mouseArea = findMouseArea(splitView);
    mouseArea->setProperty("defaultMargin", QVariant(window->screen()->physicalDotsPerInch() / 25.4));

    return app.exec();
}

Apparently, Screen::pixelDensity is calculated using the physical dots per inch of the screen, divided by 25.4, so we copy that as well. You could use any other value there.

You will need to adapt the code should a second MouseArea ever be introduced, for example.

It's still largely dependent on private API, but it doesn't touch Qt code, at least.

Mitch
  • 23,716
  • 9
  • 83
  • 122
0

Quick&Easy: enable/disable mouse and touch synthesizing

No need to patch things or doing any crazy tree lookups, just enable or disable mouse or touch synthesizing.

  • Qt::AA_SynthesizeTouchForUnhandledMouseEvents
  • Qt::AA_SynthesizeMouseForUnhandledTouchEvents

Just disable what you don't want, either mouse or touch to accept only authentic events.

Ariel M.
  • 896
  • 8
  • 24