Dans la mesure où il n'existe pas à l'heure actuelle d'éléments QML permettant de basculer d'un mode d'orientation à un autre, je propose d'exploiter le code Qt existant généré par le Wizard Qt Quick. En effet vous avez sans doute remarqué que le wizard générait une classe Qt dénommée QmlApplicationViewer. Cette classe dispose d'une méthode appropriée "setOrientation" dont l'implémentation consiste à jouer sur les attributs du QWidget pour changer l'orientation.
C'est exactement ce dont nous avons besoin : il faut donc rendre cette méthode "appelable" ("invokable" en anglais) depuis QML ; ensuite nous aurons qu'à déclarer une instance d'objet QmlApplicationViewer dans le contexte déclaratif QML.
Commençons par éditer le fichier qmlapplicationviewer.h afin de modifier la signature de la méthode "setOrientation" :
class QmlApplicationViewer : public QDeclarativeView
{
Q_OBJECT
Q_ENUMS(ScreenOrientation)
public:
enum ScreenOrientation {
ScreenOrientationLockPortrait,
ScreenOrientationLockLandscape,
ScreenOrientationAuto
};
explicit QmlApplicationViewer(QWidget *parent = 0);
virtual ~QmlApplicationViewer();
static QmlApplicationViewer *create();
void setMainQmlFile(const QString &file);
void addImportPath(const QString &path);
// Note that this will only have an effect on Symbian and Fremantle.
Q_INVOKABLE void setOrientation(ScreenOrientation orientation);
void showExpanded();
private:
explicit QmlApplicationViewer(QDeclarativeView *view, QWidget *parent);
class QmlApplicationViewerPrivate *d;
};
QApplication *createApplication(int &argc, char **argv);
Vous remarquerez églalement que j'ai déclaré le type énuméré "ScreenOrientation" comme exportable via le mot clef Q_ENUMS. Cela permettra d'utiliser cette enumération depuis QML comme paramètre lors de l'invocation de la méthode setOrientation.
Ensuite il faut éditer le contenu de la fonction main() afin :
- de déclarer l'objet QmlViewerApplication dans le contexte QML
- de déclarer le type énuméré "ScreenOrientation"
QmlApplicationViewer viewer;
viewer.setOrientation(QmlApplicationViewer::ScreenOrientationLockPortrait);
// Récupération du contexte déclaratif QML
QDeclarativeContext* context = viewer.rootContext();
// Exposition de l'objet QmlApplicationViewer afin de le rendre accessible en QML
context->setContextProperty("appviewer", &viewer);
// Enregistrement du type QmlApplicationViewer afin d'utiliser ce type en QML
qmlRegisterType<QmlApplicationViewer>("AppViewer", 1, 0, "QmlApplicationViewer");
Et c'est tout pour la partie Qt C++. Maintenant il s'agit d'utiliser la méthode QmlApplicationViewer::setOrientation depuis QML. J'ai donc créé une interface QML toute simple comme l'atteste ces deux captures d'écran :
Mode portrait |
Mode paysage |
Vous avez sans doute compris le fonctionnement : le bouton permet de changer le mode d'orientation. Pour cela j'ai défini un type QML "Bouton" comme suit :
import QtQuick 1.0
Rectangle {
property alias text: messageText.text
property alias posY: textBox.y
signal pressed
property color onButtonPressed: "grey"
property color onButtonReleased: "lightgrey"
id: textBox
color: "lightgrey"
width: messageText.width+20; height: messageText.height+10
border.width: 1
border.color: "black"
radius: 10
smooth: true
anchors.horizontalCenter: parent.horizontalCenter
Text {
id: messageText
text: "Default"
anchors.centerIn: parent
font.pointSize: 12; font.bold: true; font.family: "Helvetica"
}
MouseArea {
anchors.fill: parent
onPressed: parent.color = parent.onButtonPressed
onReleased: parent.color = parent.onButtonReleased
onClicked: textBox.pressed()
}
}
Et j'ai créé une page principale utilisant ce bouton :
import QtQuick 1.0
import AppViewer 1.0
Rectangle {
width: 360
height: 640
gradient:
Gradient {
GradientStop {
position: 0
color: "#ccc094"
}
GradientStop {
position: 0.8
color: "#777057"
}
GradientStop {
position: 1
color: "#000000"
}
}
Button
{
id: myButton
text: ""
posY:100
onPressed: {
if(state == "portrait")
{
appviewer.setOrientation(QmlApplicationViewer.ScreenOrientationLockLandscape)
state = "landscape"
}
else if(state == "landscape")
{
appviewer.setOrientation(QmlApplicationViewer.ScreenOrientationLockPortrait)
state = "portrait"
}
}
state: "portrait"
states:[
State{
name: "portrait"
PropertyChanges {
target: myButton
text: "Switch to landscape"
}
},
State{
name: "landscape"
PropertyChanges {
target: myButton
text: "Switch to portrait"
}
}
]
}
}
Les étapes importantes du listing ci-dessus sont les suivantes :
- Importer le module "AppViewer" afin de pouvoir accéder à l'objet du même nom
- Déclaration d'un bouton "Button" avec deux états : l'un gérant l'affichage en mode portrait, l'autre gérant l'affichage en mode paysage
- Appeler la méthode appviewer.setOrientation lorsque l'utilisateur clique sur le bouton avec un paramètre dont la valeur dépend de l'état courant.
Et voilà. Le code source est diponible ici