Sur cette page

Qt Quick pour les projets Android Studio

Qt Quick Les exemples de l'API Android sont des projets Android Studio

Les exemples Qt Quick pour Android API sont fournis en tant que projets Android Studio. Les dossiers des projets se trouvent dans votre emplacement d'installation de Qt Location.

Par exemple, sous le chemin d'installation par défaut de Windows, ils se trouvent ici :

C:\Qt\Examples\Qt-<patch-release-number>\platforms\android\<example-name>

Ces projets sont déjà configurés pour utiliser une version du plugin Qt Gradle compatible avec cette version de Qt.

Vue d'ensemble

Cet exemple contient un projet Qtml que vous pouvez importer dans Android Studio avec le plugin Qt Tools for Android Studio. Il existe des projets Java et Kotlin qui utilisent le projet QML comme une vue en utilisant l'API QtQuickView.

Pour plus d'informations sur le fonctionnement de QML, voir Qt Qml. Cette documentation se concentre sur la manière dont un composant QML est intégré dans des applications Android utilisant Java ou Kotlin.

Les modifications apportées à main() sont requises par Qt Quick pour les API Android

Le fichier main.cpp d'une application Qt Quick typique ressemble à ceci :

#include <QGuiApplication>
#include <QQmlApplicationEngine>

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

    QQmlApplicationEngine engine;
    QObject::connect(
        &engine,
        &QQmlApplicationEngine::objectCreationFailed,
        &app,
        []() { QCoreApplication::exit(-1); },
        Qt::QueuedConnection);
    engine.loadFromModule("MyQtQuickProject", "Main");

    return app.exec();
}

Dans main(), nous n'avons pas besoin de créer un moteur QML ou de charger un QML qui sera traité ultérieurement par les API de Qt Quick View. Tout ce dont nous avons besoin se trouve sur main():

#include <QGuiApplication>

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

    return app.exec();
}

Mise en place de la mise en page

Pour les projets Java et Kotlin, nous devons configurer la disposition des QtQuickViewsdans app/src/main/res/layout/activity_main.xml.

À l'intérieur de LinearLayout, nous configurons deux FrameLayouts pour chaque QtQuickView.

 <FrameLayout
    android:id="@+id/firstQmlFrame"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1">
</FrameLayout>

<FrameLayout
    android:id="@+id/secondQmlFrame"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1">
</FrameLayout>

Le site id est ce à quoi il est fait référence dans la MainActivity codée en Kotlin ou en Java.

Importation des classes Java des types QML générés automatiquement

Les classes Java pour nos types QML sont générées lorsque le projet Qt Quick est construit. Elles doivent être importées avant de pouvoir être utilisées dans notre MainActivity.

import org.qtproject.example.qtquickview.QmlModule.Main;
import org.qtproject.example.qtquickview.QmlModule.Second;
import org.qtproject.example.qtquickview.QmlModule.Main
import org.qtproject.example.qtquickview.QmlModule.Second

Note : Voir la variable CMake QT_ANDROID_GENERATE_JAVA_QTQUICKVIEW_CONTENTS pour plus d'informations sur la génération de code Java des composants QML.

La méthode onCreate() de MainActivity

Nous commençons par examiner la méthode MainActivity's onCreate() des projets Java et Kotlin.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    m_qmlViewBackgroundText = findViewById(R.id.qmlViewBackgroundText);
    m_qmlStatus = findViewById(R.id.qmlStatusText);
    m_androidControlsLayout = findViewById(R.id.javaRelative);
    m_colorBox = findViewById(R.id.qmlColorBox);
    m_switch = findViewById(R.id.disconnectQmlListenerSwitch);
    m_switch.setOnClickListener(view -> switchListener());
    QtQuickView m_firstQuickView = new QtQuickView(this);
    QtQuickView m_secondQuickView = new QtQuickView(this);

    // Set status change listener for m_qmlView
    // listener implemented below in OnStatusChanged
    m_firstQmlContent.setStatusChangeListener(this);
    m_secondQmlContent.setStatusChangeListener(this);
    final ViewGroup.LayoutParams params = new FrameLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    FrameLayout m_firstQmlFrameLayout = findViewById(R.id.firstQmlFrame);
    m_firstQmlFrameLayout.addView(m_firstQuickView, params);
    FrameLayout m_secondQmlFrameLayout = findViewById(R.id.secondQmlFrame);
    m_secondQmlFrameLayout.addView(m_secondQuickView, params);
    m_firstQuickView.loadContent(m_firstQmlContent);
    m_secondQuickView.loadContent(m_secondQmlContent);

    Button m_changeColorButton = findViewById(R.id.changeQmlColorButton);
    m_changeColorButton.setOnClickListener(view -> onClickListener());
    Button m_rotateQmlGridButton = findViewById(R.id.rotateQmlGridButton);
    m_rotateQmlGridButton.setOnClickListener(view -> rotateQmlGrid());
}
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    m_binding = ActivityMainBinding.inflate(layoutInflater)
    val view = m_binding.root
    setContentView(view)

    m_binding.disconnectQmlListenerSwitch.setOnCheckedChangeListener { button, checked ->
        switchListener(
            button,
            checked
        )
    }

    val firstQtQuickView = QtQuickView(this)
    val secondQtQuickView = QtQuickView(this)

    // Set status change listener for m_qmlView
    // listener implemented below in OnStatusChanged
    m_firstQmlContent.setStatusChangeListener(this)
    m_secondQmlContent.setStatusChangeListener(this)

    val params: ViewGroup.LayoutParams = FrameLayout.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
    )
    m_binding.firstQmlFrame.addView(firstQtQuickView, params)
    m_binding.secondQmlFrame.addView(secondQtQuickView, params)
    firstQtQuickView.loadContent(m_firstQmlContent)
    secondQtQuickView.loadContent(m_secondQmlContent)

    m_binding.changeQmlColorButton.setOnClickListener { onClickListener() }
    m_binding.rotateQmlGridButton.setOnClickListener { rotateQmlGrid() }
}

Remarque : dans le projet Kotlin, nous utilisons la liaison View pour accéder aux composants de l'interface utilisateur de l'application :

m_binding = ActivityMainBinding.inflate(layoutInflater)
val view = m_binding.root
setContentView(view)

Dans la méthode onCreate(), les variables déclarées précédemment sont initialisées avec de nouvelles instances QtQuickView. Ces instances prennent les Context de l'activité Java/Kotlin comme arguments.

QtQuickView m_firstQuickView = new QtQuickView(this);
QtQuickView m_secondQuickView = new QtQuickView(this);
val firstQtQuickView = QtQuickView(this)
val secondQtQuickView = QtQuickView(this)

Les instances QtQuickView sont ajoutées à la disposition Android avec les paramètres de disposition appropriés.

final ViewGroup.LayoutParams params = new FrameLayout.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
FrameLayout m_firstQmlFrameLayout = findViewById(R.id.firstQmlFrame);
m_firstQmlFrameLayout.addView(m_firstQuickView, params);
FrameLayout m_secondQmlFrameLayout = findViewById(R.id.secondQmlFrame);
m_secondQmlFrameLayout.addView(m_secondQuickView, params);
val params: ViewGroup.LayoutParams = FrameLayout.LayoutParams(
    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
)
m_binding.firstQmlFrame.addView(firstQtQuickView, params)
m_binding.secondQmlFrame.addView(secondQtQuickView, params)

Les classes Java Main et Second héritent de la classe QtQuickViewContent. Ces classes sont générées à partir du projet QML que nous avons importé.

private final Main m_firstQmlContent = new Main();
private final Second m_secondQmlContent = new Second();
private val m_firstQmlContent: Main = Main()
private val m_secondQmlContent: Second = Second()

Le contenu de Qt Quick est chargé par la méthode QtQuickView.loadContent(), qui prend un QtQuickViewContent comme argument.

m_firstQuickView.loadContent(m_firstQmlContent);
m_secondQuickView.loadContent(m_secondQmlContent);
firstQtQuickView.loadContent(m_firstQmlContent)
secondQtQuickView.loadContent(m_secondQmlContent)

Interagir avec les composants QML

Pour interagir avec les composants QML intégrés, nous implémentons l'interface QtQmlStatusChangeListener et surchargeons la méthode onStatusChanged pour obtenir l'état de chargement du QtQuickViewContent en cours de chargement dans le QtQuickView.

public class MainActivity extends AppCompatActivity implements
QtQmlStatusChangeListener {
    ...
}
class MainActivity : AppCompatActivity(), QtQmlStatusChangeListener {
    ...
}

La mise en œuvre de onStatusChanged:

@Override
public void onStatusChanged(QtQmlStatus qtQmlStatus, QtQuickViewContent content) {
    Log.i(TAG, "Status of QtQuickView: " + qtQmlStatus);

    // Show current QML View status in a textview
    m_qmlStatus.setText(getString(R.string.qml_view_status, m_statusNames.get(qtQmlStatus)));
    updateColorDisplay();

    if (content == m_firstQmlContent) {
        // Connect signal listener to "onClicked" signal from main.qml
        // addSignalListener returns int which can be used later to identify the listener
        if (qtQmlStatus == QtQmlStatus.READY && m_switch.isChecked()) {
            m_qmlButtonSignalListenerId = m_firstQmlContent.connectOnClickedListener(
                    (String name, Void v) -> {
                        Log.i(TAG, "QML button clicked");
                        m_androidControlsLayout.setBackgroundColor(Color.parseColor(
                                m_colors.getColor()
                        ));
                    });
        }
    }
}
override fun onStatusChanged(status: QtQmlStatus?, content: QtQuickViewContent?) {
    Log.v(TAG, "Status of QtQuickView: $status")

    // Show current QML View status in a textview
    m_binding.qmlStatusText.text = getString(R.string.qml_view_status, m_statusNames[status])

    updateColorDisplay()

    if (content == m_firstQmlContent) {
        // Connect signal listener to "onClicked" signal from main.qml
        // addSignalListener returns int which can be used later to identify the listener
        if (status == QtQmlStatus.READY && m_binding.disconnectQmlListenerSwitch.isChecked) {
            m_qmlButtonSignalListenerId =
                m_firstQmlContent.connectOnClickedListener { _: String, _: Void? ->
                    Log.i(TAG, "QML button clicked")
                    m_binding.kotlinRelative.setBackgroundColor(
                        Color.parseColor(
                            m_colors.getColor()
                        )
                    )
                }
        }
    }
}

Le site MainActivity est défini comme le site statusChangeListener des sites m_mainQmlContent et m_secondQmlContent avec la méthode QtQuickViewContent.setStatusChangeListener.

m_firstQmlContent.setStatusChangeListener(this);
m_secondQmlContent.setStatusChangeListener(this);
m_firstQmlContent.setStatusChangeListener(this)
m_secondQmlContent.setStatusChangeListener(this)

La fonction de rappel surchargée onStatusChanged() reçoit le signal StatusChanged() contenant l'état actuel, une Enum QtQmlStatus, du chargement de la QtQuickViewContent actuelle dans le QtQuickView. Si cette QtQmlStatus est confirmée comme étant QtQmlStatus.READY, nous pouvons commencer à interagir avec la vue QML.

Obtenir et définir les valeurs des propriétés des composants QML

L'obtention et la définition des valeurs des propriétés des composants QML s'effectuent par le biais des méthodes décrites dans la classe Main.java. Dans ce cas, nous utilisons les méthodes m_mainQmlContent.setColorStringProperty() et m_mainQmlContent.getColorStringProperty(). Ces méthodes sont générées en fonction des propriétés du composant QML.

public void onClickListener() {
    // Set the QML view root object property "colorStringFormat" value to
    // color from Colors.getColor()
    m_firstQmlContent.setColorStringFormat(m_colors.getColor());
    updateColorDisplay();
}
private void updateColorDisplay() {
    String qmlBackgroundColor = m_firstQmlContent.getColorStringFormat();
    // Display the QML View background color code
    m_qmlViewBackgroundText.setText(qmlBackgroundColor);

    // Display the QML View background color in a view
    // if qmlBackGroundColor is not null
    if (qmlBackgroundColor != null) {
        m_colorBox.setBackgroundColor(Color.parseColor(qmlBackgroundColor));
    }
}
private fun onClickListener() {
    // Set the QML view root object property "colorStringFormat" value to
    // color from Colors.getColor()
    m_firstQmlContent.colorStringFormat = m_colors.getColor()
    updateColorDisplay()
}

private fun updateColorDisplay() {
    val qmlBackgroundColor = m_firstQmlContent.colorStringFormat
    // Display the QML View background color code
    m_binding.qmlViewBackgroundText.text = qmlBackgroundColor
    // Display the QML View background color in a view
    // if qmlBackgroundColor is not null
    if (qmlBackgroundColor != null) {
        m_binding.qmlColorBox.setBackgroundColor(Color.parseColor(qmlBackgroundColor))
    }
}

Avec la méthode m_mainQmlContent.setColorStringProperty(), nous définissons la valeur de la propriété colorStringFormat de l'objet m_mainQmlContent comme une valeur de couleur aléatoire récupérée dans la classe Colors.java (ou Colors.kt).

La méthode m_mainQmlContent.getColorStringProperty() est utilisée ici pour récupérer la couleur d'arrière-plan actuelle de l'objet racine du m_mainQmlContent et l'afficher à l'utilisateur du côté Java/Kotlin Android de l'application.

m_secondQmlContent m_mainQmlContent possède un composant QML Grid que nous pouvons faire pivoter du côté Java avec la méthode m_secondQmlContent.setGridRotation() générée.

private void rotateQmlGrid() {
    Integer previousGridRotation = m_secondQmlContent.getGridRotation();
    if (previousGridRotation != null) {
        m_secondQmlContent.setGridRotation(previousGridRotation + 45);
    }
}
private fun rotateQmlGrid() {
    val previousGridRotation = m_secondQmlContent.gridRotation
    if (previousGridRotation != null) {
        m_secondQmlContent.gridRotation = previousGridRotation + 45
    }
}

Écouteurs de signaux

La classe QtQuickViewContent propose les méthodes connectSignalListener() et disconnectSignalListener() qui sont utilisées pour connecter et déconnecter les auditeurs de signaux entre les signaux déclarés dans l'objet racine du composant QML. La méthode QtQuickViewContent.connectSignalListener() renvoie un identifiant unique de l'auditeur de signaux, que nous stockons et utilisons ultérieurement pour identifier et déconnecter l'auditeur.

Ici, nous connectons un auditeur de signaux au signal onClicked() du composant QML :

if (qtQmlStatus == QtQmlStatus.READY && m_switch.isChecked()) {
    m_qmlButtonSignalListenerId = m_firstQmlContent.connectOnClickedListener(
            (String name, Void v) -> {
                Log.i(TAG, "QML button clicked");
                m_androidControlsLayout.setBackgroundColor(Color.parseColor(
                        m_colors.getColor()
                ));
            });
}
if (status == QtQmlStatus.READY && m_binding.disconnectQmlListenerSwitch.isChecked) {
    m_qmlButtonSignalListenerId =
        m_firstQmlContent.connectOnClickedListener { _: String, _: Void? ->
            Log.i(TAG, "QML button clicked")
            m_binding.kotlinRelative.setBackgroundColor(
                Color.parseColor(
                    m_colors.getColor()
                )
            )
        }
}

Le signal onClicked() est émis chaque fois que le bouton du composant QML est cliqué. Cet écouteur reçoit alors ce signal, et la couleur d'arrière-plan de la mise en page du côté Android de l'application est réglée sur une valeur de couleur aléatoire récupérée dans la classe Colors.java.

Ensuite, l'auditeur de signaux est déconnecté à l'aide de la méthode QtQuickViewContent.disconnectSignalListener() en lui donnant l'identifiant unique de l'auditeur de signaux.

m_firstQmlContent.disconnectSignalListener(m_qmlButtonSignalListenerId);
m_firstQmlContent.disconnectSignalListener(m_qmlButtonSignalListenerId)

Si vous ne l'avez pas encore fait, consultez le cours Qt Academy : Embedding Qt Quick 3D Content in an Android App qui présente les outils et les API référencés dans cet exemple.

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.