Orientation de l'écran en QML

| Christophe Dumez | traducteur : Thibaut Cuvelier |

Au lancement d'une application sur un périphérique mobile, il est souvent utile de détecter l'orientation de l'écran pour adapter la disposition visuelle. Malheureusement, QML n'est pas encore capable de détecter cette orientation lui-même. Cet article explique comment utiliser l'API de capteurs de QtMobility (Sensors) en QML.

Commentez

- Titre : Orientation de l'écran en QML

- Auteurs : Christophe Dumez, traducteur : Thibaut Cuvelier

- Parution : 2 février 2012

- Mise à jour : 25 février 2012

- Licence : Copyright ® 2010 Christophe Dumez. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Article original

- II. Une classe Orientation

- III. Exposition à QML

- IV. Remerciements

I - Article original

Cet article est une adaptation en langue française de Screen orientation detection for QML.

II - Une classe Orientation

On écrit tout d'abord une classe Orientation qui utilise un QOrientationSensor pour détecter les changements d'orientation du périphérique.

En voici l'en-tête orientation.h :

class Orientation : public QObject
{
Q_OBJECT
Q_PROPERTY(QString state READ state NOTIFY orientationChanged)

public:
explicit Orientation(QObject *parent = 0);
~Orientation();
inline QString state() const { return m_state; }

signals:
void orientationChanged();

private slots:
void onReadingChanged();

private:
QString m_state;
QtMobility::QOrientationSensor* m_sensor;

};

On a utilisé la macro Q_PROPERTY() pour rendre la propriété d'état disponible depuis QML. NOTIFY orientationChanged est important, puisque cette partie s'assure que QML sera notifié lors d'un changement d'orientation (c'est-à-dire quand le signal orientationChanged() est émis). L'utilisation de cette macro pour exposer des données depuis C++ à QML est expliqué dans la documentation.

L'implémentation est la suivante :

Orientation::Orientation(QObject *parent) :
QObject(parent), m_state("Portrait")
{
m_sensor = new QOrientationSensor(this);
connect(m_sensor, SIGNAL(readingChanged()), SLOT(onReadingChanged()));
m_sensor->start();
}

Orientation::~Orientation() {
delete m_sensor;
}

void Orientation::onReadingChanged()
{
QOrientationReading* reading = m_sensor->reading();
switch(reading->orientation())
{
case QOrientationReading::TopUp:
m_state = "Landscape";
emit orientationChanged();
break;
case QOrientationReading::TopDown:
m_state = "LandscapeInverted";
emit orientationChanged();
break;
case QOrientationReading::LeftUp:
m_state = "Portrait";
emit orientationChanged();
break;
case QOrientationReading::RightUp:
m_state = "PortraitInverted";
emit orientationChanged();
default:
break;
}
}

III - Exposition à QML

Ensuite, on instancie cet objet et on l'expose à QML avec QDeclarativeContext::setContextProperty() :

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

QDeclarativeView view;
view.setResizeMode(QDeclarativeView::SizeRootObjectToView);
const QRect screenGeometry = QApplication::desktop()->screenGeometry();
view.setGeometry(screenGeometry);
QDeclarativeContext *context = view.rootContext();
context->setContextProperty("screenWidth", screenGeometry.width());
context->setContextProperty("screenHeight", screenGeometry.height());
context->setContextProperty("Orientation", new Orientation(&app));
view.setSource(QUrl("qrc:/qml/ScreenOrientationQML/main.qml"));
view.showFullScreen();

return app.exec();
}

Côté QML, on l'utilise comme ceci :

import Qt 4.7

Rectangle {
id: window
width: screenWidth
height: screenHeight
anchors.centerIn: parent
state: Orientation.state

Text {
anchors.fill: parent
text: "Hello World!"
}

states:  [
State {
name: "Landscape"
PropertyChanges {
target: window
rotation: 0
width: screenWidth
height: screenHeight
x: 0
y: 0
}
},
State {
name: "LandscapeInverted"
PropertyChanges {
target: window
rotation: 180
width: screenWidth
height: screenHeight
x: 0
y: 0
}
},
State {
name: "Portrait"
PropertyChanges {
target: window
rotation: 270
width: screenHeight
height: screenWidth
x: (screenWidth - screenHeight) / 2
y: -(screenWidth - screenHeight) / 2
}
},
State {
name: "PortraitInverted"
PropertyChanges {
target: window
rotation: 90
width: screenHeight
height: screenWidth
x: (screenWidth - screenHeight) / 2
y: -(screenWidth - screenHeight) / 2
}
}
]

transitions: [
Transition {
from: "*"
to: "*"

ParallelAnimation {
RotationAnimation {
properties: "rotation"
duration: 250
direction: RotationAnimation.Shortest
}
PropertyAnimation {
target: window
properties: "x,y,width,height"
duration: 250
}
}
}
]
}

Comme on peut le voir, on observe quatre états QML, un par orientation ; l'application se base sur la propriété d'état de l'objet Orientation pour déterminer lequel utiliser. On a aussi ajouté quelques animations de transition pour améliorer l'affichage.

IV - Remerciements

Merci à Guillaume Belz et Stoyak pour leur relecture attentive !