Qt Quick 안드로이드 스튜디오 프로젝트용

개요

이 예제에는 안드로이드 스튜디오용 Qt 도구 플러그인을 사용하여 안드로이드 스튜디오로 임포트할 수 있는 QML 프로젝트와 QtQuickView API를 활용하여 QML 프로젝트를 뷰로 사용하는 Java 및 Kotlin 프로젝트가 포함되어 있습니다.

QML 작동 방식에 대한 자세한 내용은 Qt Qml. 이 문서에서는 QML 컴포넌트가 Java 및 Kotlin 기반 Android 애플리케이션에 임베드되는 방법에 중점을 두고 설명합니다.

먼저 Java 및 Kotlin 프로젝트의 MainActivity 의 onCreate() 메서드를 살펴봅니다.

Java 기반 프로젝트의 경우

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

    m_mainLinear = findViewById(R.id.mainLinear);
    m_getPropertyValueText = findViewById(R.id.getPropertyValueText);
    m_qmlStatus = findViewById(R.id.qmlStatusText);
    m_androidControlsLayout = findViewById(R.id.javaLinear);
    m_box = findViewById(R.id.qmlColorBox);
    m_switch = findViewById(R.id.disconnectQmlListenerSwitch);
    m_switch.setOnClickListener(view -> switchListener());
    m_qtQuickView = new QtQuickView(this);

    // Set status change listener for m_qmlView
    // listener implemented below in OnStatusChanged
    m_mainQmlContent.setStatusChangeListener(this);
    m_secondQmlContent.setStatusChangeListener(this);
    ViewGroup.LayoutParams params = new FrameLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    m_qmlFrameLayout = findViewById(R.id.qmlFrame);
    m_qmlFrameLayout.addView(m_qtQuickView, params);
    m_qtQuickView.loadContent(m_mainQmlContent);

    Button m_changeColorButton = findViewById(R.id.changeQmlColorButton);
    m_changeColorButton.setOnClickListener(view -> onClickListener());
    Button m_loadMainQmlButton = findViewById(R.id.loadMainQml);
    m_loadMainQmlButton.setOnClickListener(view -> loadMainQml());
    Button m_loadSecondQmlButton = findViewById(R.id.loadSecondQml);
    m_loadSecondQmlButton.setOnClickListener(view -> loadSecondQml());
    Button m_rotateQmlGridButton = findViewById(R.id.rotateQmlGridButton);
    m_rotateQmlGridButton.setOnClickListener(view -> rotateQmlGrid());

    // Check target device orientation on launch
    handleOrientationChanges();
}

Kotlin 기반 프로젝트의 경우:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    m_binding = ActivityMainBinding.inflate(layoutInflater)
    val view = m_binding.root
    setContentView(view)

    m_binding.disconnectQmlListenerSwitch.setOnClickListener { switchListener() }

    m_qtQuickView = QtQuickView(this)

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

    val params: ViewGroup.LayoutParams = FrameLayout.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
    )
    m_binding.qmlFrame.addView(m_qtQuickView, params)
    m_qtQuickView!!.loadContent(m_mainQmlContent)

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

    // Check target device orientation on launch
    handleOrientationChanges()
}

참고: Kotlin 프로젝트에서는 애플리케이션의 UI 구성 요소에 액세스하기 위해 View 바인딩을 사용합니다:

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

onCreate() 메서드 내에서 이전에 선언된 변수 m_qtQuickView 가 새 QtQuickView로 초기화됩니다. 이 새 QtQuickView 인스턴스는 Java/Kotlin 활동의 컨텍스트를 인수로 제공하여 생성됩니다.

Java 기반 프로젝트의 경우:

m_qtQuickView = new QtQuickView(this);

Kotlin 기반 프로젝트의 경우:

m_qtQuickView = QtQuickView(this)

MainSecond Java 클래스는 QtQuickViewContent 클래스를 상속합니다. 이러한 클래스는 임포트한 QML 프로젝트에서 생성됩니다. 이 예제에서는 이러한 QML 컴포넌트를 사용하여 안드로이드 프로젝트에 QML 컴포넌트를 임베드하는 방법을 설명합니다.

Java 기반 프로젝트의 경우:

private final Main m_mainQmlContent = new Main();
private final Second m_secondQmlContent = new Second();

Kotlin 기반 프로젝트의 경우(선언 시 초기화됨):

private var m_mainQmlContent: Main = Main()
private val m_secondQmlContent: Second = Second()

m_mainQmlContentQtQuickView.loadContent() 메서드를 통해 m_qtQuickView 에 로드되며, 은 QtQuickViewContent 을 인수로 받습니다.

Java 기반 프로젝트의 경우:

m_qtQuickView.loadContent(m_mainQmlContent);

Kotlin 기반 프로젝트의 경우:

m_qtQuickView!!.loadContent(m_mainQmlContent)

m_qtQuickView 이 적절한 레이아웃 매개 변수와 함께 안드로이드 프레임레이아웃 뷰그룹에 추가됩니다.

Java 기반 프로젝트의 경우:

ViewGroup.LayoutParams params = new FrameLayout.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
m_qmlFrameLayout = findViewById(R.id.qmlFrame);
m_qmlFrameLayout.addView(m_qtQuickView, params);

Kotlin 기반 프로젝트의 경우:

val params: ViewGroup.LayoutParams = FrameLayout.LayoutParams(
    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
)
m_binding.qmlFrame.addView(m_qtQuickView, params)

QML 컴포넌트와 상호 작용하기

임베디드 QML 컴포넌트와 상호 작용하기 위해 QtQmlStatusChangeListener 인터페이스를 구현하고 onStatusChanged 메서드를 재정의하여 현재 로드 중인 QtQuickViewContent의 로드 상태를 m_qtQuickView 로 가져옵니다.

Java 기반 프로젝트의 경우:

public class MainActivity extends AppCompatActivity implements
QtQmlStatusChangeListener{
    ...
}

Kotlin 기반 프로젝트의 경우:

class MainActivity : AppCompatActivity(), QtQmlStatusChangeListener{
    ...
}

onStatusChanged 구현.

Java 기반 프로젝트의 경우:

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

    final String qmlStatus = getResources().getString(R.string.qml_view_status)
            + m_statusNames.get(qtQmlStatus);

    // Show current QML View status in a textview
    m_qmlStatus.setText(qmlStatus);

    // 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_mainQmlContent.connectOnClickedListener(
                (String name, Void v) -> {
                    Log.i(TAG, "QML button clicked");
                    m_androidControlsLayout.setBackgroundColor(Color.parseColor(
                            m_colors.getColor()
                    ));
                });

    }
}

Kotlin 기반 프로젝트의 경우:

override fun onStatusChanged(status: QtQmlStatus?) {
    Log.v(TAG, "Status of QtQuickView: $status")

    val qmlStatus = (resources.getString(R.string.qml_view_status)
            + m_statusNames[status])

    // Show current QML View status in a textview
    m_binding.qmlStatusText.text = qmlStatus

    // 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_mainQmlContent.connectOnClickedListener { _: String, _: Void? ->
                Log.i(TAG, "QML button clicked")
                m_binding.kotlinLinear.setBackgroundColor(
                    Color.parseColor(
                        m_colors.getColor()
                    )
                )
            }
    }
}

onStatusChanged 수신기는 m_mainQmlContentm_secondQmlContentstatusChangeListenerQtQuickViewContent.setStatusChangeListener(QtQmlStatusChangeListener onStatusChanged()) 메서드의 로 설정됩니다.

Java 기반 프로젝트의 경우:

m_mainQmlContent.setStatusChangeListener(this);
m_secondQmlContent.setStatusChangeListener(this);

Kotlin 기반 프로젝트의 경우:

m_mainQmlContent.setStatusChangeListener(this)
m_secondQmlContent.setStatusChangeListener(this)

재정의된 콜백 함수 onStatusChanged() 는 현재 QtQuickViewContent를 m_qtQuickView 로 로드하는 현재 상태(공용 Enum QtQmlStatus)를 포함하는 StatusChanged() 신호를 수신합니다. 이 QtQmlStatusQtQmlStatus.READY 로 확인되면 QML 뷰와 상호 작용을 시작할 수 있습니다.

QtQuickView에 QtQuickViewContents 로드하기

가져온 QML 프로젝트에 여러 개의 QtQuickViewContent를 가질 수 있으며, QtQuickViewContent를 인수로 받는 QtQuickView.loadContent() 메서드를 사용하여 현재 로드된 QtQuickView의 콘텐츠를 전환할 수 있습니다. 이 메서드는 주어진 QtQuickViewContent를 로드하고 이전 콘텐츠가 있으면 언로드합니다.

Java 기반 프로젝트의 경우:

private void loadSecondQml() {
    m_qtQuickView.loadContent(m_secondQmlContent);

    // Reset box color and color text after component reload
    m_box.setBackgroundColor(Color.parseColor("#00ffffff"));
    m_getPropertyValueText.setText("");
}

private void loadMainQml() {
    m_qtQuickView.loadContent(m_mainQmlContent);

    // Reset box color and color text after component reload
    m_box.setBackgroundColor(Color.parseColor("#00ffffff"));
    m_getPropertyValueText.setText("");
}

Kotlin 기반 프로젝트의 경우:

private fun loadSecondQml() {
    m_qtQuickView!!.loadContent(m_secondQmlContent)

    // Reset box color and color text after component reload
    m_binding.qmlColorBox.setBackgroundColor(Color.parseColor("#00ffffff"))
    m_binding.getPropertyValueText.text = ""
}

private fun loadMainQml() {
    m_qtQuickView!!.loadContent(m_mainQmlContent)

    // Reset box color and color text after component reload
    m_binding.qmlColorBox.setBackgroundColor(Color.parseColor("#00ffffff"))
    m_binding.getPropertyValueText.text = ""
}

QML 컴포넌트 속성 값 가져오기 및 설정하기

QML 컴포넌트 속성 값을 가져오고 설정하는 작업은 Main.java 클래스에 설명된 메서드를 통해 이루어집니다. 이 경우 m_mainQmlContent.setColorStringProperty()m_mainQmlContent.getColorStringProperty() 메서드를 사용합니다. 이러한 메서드는 QML 컴포넌트에 포함된 속성에 따라 생성됩니다.

Java 기반 프로젝트의 경우:

public void onClickListener() {
    // Set the QML view root object property "colorStringFormat" value to
    // color from Colors.getColor()
    m_mainQmlContent.setColorStringFormat(m_colors.getColor());

    String qmlBackgroundColor = m_mainQmlContent.getColorStringFormat();
    // Display the QML View background color code
    m_getPropertyValueText.setText(qmlBackgroundColor);

    // Display the QML View background color in a view
    // if qmlBackGroundColor is not null
    if (qmlBackgroundColor != null) {
        m_box.setBackgroundColor(Color.parseColor(qmlBackgroundColor));
    }
}

Kotlin 기반 프로젝트의 경우:

private fun onClickListener() {
    // Set the QML view root object property "colorStringFormat" value to
    // color from Colors.getColor()
    m_mainQmlContent.colorStringFormat = m_colors.getColor()

    val qmlBackgroundColor = m_mainQmlContent.colorStringFormat

    // Display the QML View background color code
    m_binding.getPropertyValueText.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))
    }
}

m_mainQmlContent.setColorStringProperty() 메서드를 사용하여 m_mainQmlContentcolorStringFormat 속성 값을 Colors.java (또는 Colors.kt) 클래스에서 가져온 임의의 색상 값으로 설정합니다.

여기서 m_mainQmlContent.getColorStringProperty() 메서드는 m_mainQmlContent의 루트 객체의 현재 배경색을 가져온 다음 애플리케이션의 Java/Kotlin Android 쪽에서 사용자에게 표시하는 데 사용됩니다.

m_secondQmlContent 에는 생성된 m_secondQmlContent.setGridRotation() 메서드를 사용하여 Java 측에서 회전할 수 있는 Grid QML 컴포넌트가 있습니다.

Java 기반 프로젝트의 경우:

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

Kotlin 기반 프로젝트의 경우

private fun rotateQmlGrid() {
    val previousGridRotation = m_secondQmlContent.gridRotation
    if (previousGridRotation != null) {
        m_secondQmlContent.gridRotation = previousGridRotation + 45
    }
}

신호 수신기

QtQuickViewContent 클래스는 QML 컴포넌트 루트 객체에 선언된 신호 간에 신호 리스너를 연결하고 연결을 끊는 데 사용되는 connectSignalListener()disconnectSignalListener() 메서드를 제공합니다. QtQuickViewContent.connectSignalListener() 메서드는 고유한 신호 리스너 ID를 반환하여 나중에 리스너를 식별하고 연결을 끊을 때 저장하고 사용합니다.

여기서는 신호 수신기를 QML 컴포넌트의 onClicked() 신호에 연결합니다.

Java 기반 프로젝트의 경우:

if (qtQmlStatus == QtQmlStatus.READY && !m_switch.isChecked()) {
    m_qmlButtonSignalListenerId = m_mainQmlContent.connectOnClickedListener(
            (String name, Void v) -> {
                Log.i(TAG, "QML button clicked");
                m_androidControlsLayout.setBackgroundColor(Color.parseColor(
                        m_colors.getColor()
                ));
            });

}

Kotlin 기반 프로젝트의 경우:

if (status == QtQmlStatus.READY && !m_binding.disconnectQmlListenerSwitch.isChecked) {
    m_qmlButtonSignalListenerId =
        m_mainQmlContent.connectOnClickedListener { _: String, _: Void? ->
            Log.i(TAG, "QML button clicked")
            m_binding.kotlinLinear.setBackgroundColor(
                Color.parseColor(
                    m_colors.getColor()
                )
            )
        }
}

QML 컴포넌트의 버튼이 클릭될 때마다 onClicked() 신호가 방출됩니다. 그러면 이 리스너가 해당 신호를 수신하고 애플리케이션의 Android 쪽을 유지하는 레이아웃의 배경색이 Colors.java 클래스에서 가져온 임의의 색상 값으로 설정됩니다.

그런 다음 QtQuickViewContent.disconnectSignalListener() 메서드를 사용하여 고유한 신호 리스너 ID를 부여하여 신호 리스너의 연결을 끊습니다.

Java 기반 프로젝트의 경우

m_mainQmlContent.disconnectSignalListener(m_qmlButtonSignalListenerId);

Kotlin 기반 프로젝트의 경우

m_mainQmlContent.disconnectSignalListener(m_qmlButtonSignalListenerId)

© 2025 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.