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 !