Qt with Cascades UI Examples Documentation

Contents

Grue Detector Example

Files:

Description

The Grue Detector example demonstrates how to use sensors from the QtSensors module to warn you about the chance of being eaten by a Grue.

Overview

In this example we'll learn how to use the QLightSensor, QLightFilter and QLightReading classes to retrieve the current LUX value from the light sensor of the device. If we are below a given threshold, we'll start a timer and increase the chance of being eaten every second.

The UI

The UI of this sample application consists of an ImageView that shows the grue and a Label that shows a status message.

The business logic of the application is encapsulated in the GrueDetector class which is made available to the UI under the name '_detector'.

                Grue {
                    horizontalAlignment: HorizontalAlignment.Center
                    verticalAlignment: VerticalAlignment.Center
                    scaleX: _detector.chance/100
                    scaleY: _detector.chance/100

                    chance: _detector.chance
                }

The UI of the Grue (the eyes and the mouth) are put into a separated file Grue.qml, which we use in main.qml. Depending on the chance of being eaten, we scale up/down the Grue component. If the chance is low, the grue is small, if the chance is high, the grue is large.

                Label {
                    horizontalAlignment: HorizontalAlignment.Center
                    verticalAlignment: VerticalAlignment.Bottom
                    text: _detector.chance > 90 ? qsTr ("Time to run!")
                                                : qsTr ("Chance to be eaten at %1%").arg(_detector.chance)
                    textStyle {
                        base: SystemDefaults.TextStyles.TitleText
                        color: Color.White
                    }
                }

The status label shows the current numeric chance value or a warning message if the chance is too high.

GrueDetector

The GrueDetector class encapsulates the business logic of the application. It contains a QLightSensor object, which does the low-level communication with the light sensor of the device, and provides a property 'chance' to make the calculated chance value available to the UI. It inherits from QCompassFilter and reimplements the 'bool filter(QLightReading*)' method to retrieve the sensor data from the QLightSensor object.

    class GrueDetector : public QObject, public QLightFilter
    {
        Q_OBJECT

        // The property to access the chance value of being eaten by a grue
        Q_PROPERTY(int chance READ chance NOTIFY chanceChanged)

    public:
        GrueDetector(QObject *parent = 0);

    Q_SIGNALS:
        // The change notification signal of the chance property
        void chanceChanged();

    protected:
        /**
         * This method is reimplemented from the QLightFilter interface and is
         * called by the QLightSensor whenever new values are available.
         */
        bool filter(QLightReading *reading);

    private Q_SLOTS:
        // This method is called every second if we are in an dark environment
        void increaseChance();

    private:
        // The accessor method for the chance property
        int chance() const;

        // The value of the chance property
        int m_chance;

        // The light sensor
        QLightSensor m_sensor;

        // A timer to calculate the chance
        QTimer *m_darkTimer;
    };

Inside the constructor we try to connect the QLightSensor object to the hardware backend. If that's successful, we register the GrueDetector class as filter for the QLightSensor object and start the sensor to gather data.

    GrueDetector::GrueDetector(QObject *parent)
        : QObject(parent)
        , m_chance(0)
        , m_darkTimer(new QTimer(this))
    {
        // At first we have to connect to the sensor backend...
        if (!m_sensor.connectToBackend()) {
            qWarning() << "Cannot connect to light sensor backend!";
        }

        // ... and then add a filter that will process the reported data
        m_sensor.addFilter(this);

        // Start the gathering of data
        m_sensor.start();

        connect(m_darkTimer, SIGNAL(timeout()), this, SLOT(increaseChance()));
    }

The 'bool filter(QLightReading*)' method is called whenever the QLightSensor object retrieved new data from the hardware sensor. Inside this method we check whether the current LUX value is smaller than 10. In this case it's dark around us, so we start a timer that increases the chance value every second by 10%. If the LUX value is larger than 10, we reset the chance value back to 0%.

    bool GrueDetector::filter(QLightReading *reading)
    {
        if (reading->lux() < 10) { // Dark enough for meeting a Grue
            if (!m_darkTimer->isActive())
                m_darkTimer->start(1000);
        } else { // everything is fine...
            m_darkTimer->stop();
            m_chance = 0;
            emit chanceChanged();
        }

        // Do no further processing of the sensor data
        return false;
    }