IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Orientation de l'écran en QML

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 Donner une note à l´article (5)

Article lu   fois.

Les deux auteurs

Profil ProSite personnel

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

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 :

 
TéléchargerSélectionnez
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 :

 
TéléchargerSélectionnez
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() :

 
Sélectionnez
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 :

 
Sélectionnez
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 !

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Copyright © 2010 Christophe Dumez. Aucune reproduction, même partielle, ne peut être faite de ce site ni 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.