Evgenii Legotckoi
27 лютого 2018 р. 13:40

Android. Java проти Qt QML - Підручник 002. Обробка натискань кнопок

Після того, як ми познайомилися з Hello World зі світу Java і Qt QML під Android, пропоную написати програму, яка матиме дві кнопки і натисканням на ці кнопки буде змінювати текст у невеликому текстовому полі. Програми мають виглядати однаково, але не на 100 відсотків ідентично. За бажання цього можна досягти, але в цьому прикладі не обов'язково.

В обох випадках використовуватиметься Material Design .

Перш ніж подивитися на програмний код, подивимося на зовнішній вигляд обох програм.

Додаток, написаний на Java


А тепер програма, яка написана на Qt QML

Ви можете бачити, що результат вийшов однаковим, і водночас ви можете бачити деякі візуальні відмінності. Якщо чесно, то варіант Material Design, який використовується в Qt QML, мені більше подобається, ніж той, що використовується в Java за замовчуванням.

А тепер перейдемо до вивчення програмного коду наших двох програм.

Java

Я відключив ToolBar, оскільки інформація щодо нього була дана ще в прикладі з Hello World, а в даному випадку для порівняння коду нам він уже не знадобиться.

activity_main.xml

Файл верстки нашої головної діяльності. Для того, щоб помістити обидві кнопки в нижню частину екрана, знадобилося використовувати Layout в горизонтальній орієнтації, що в QML вам це не знадобиться для подібного виду кнопки в цьому прикладі. Оскільки в QML використовуються якорі , які подібні за принципом з роботою властивостей layout_constraint , але на мій погляд дещо гнучкіші.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.evileg.javabuttons.MainActivity">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:text="Press Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:orientation="horizontal"
        android:gravity="center_horizontal"
        android:weightSum="2"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">

        <Button
            android:id="@+id/OkButton"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="Ok"
            android:layout_weight="1"/>

        <Button
            android:id="@+id/Cancelbutton"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="Cancel"
            android:layout_weight="1"/>
    </LinearLayout>

</android.support.constraint.ConstraintLayout>

MainActivity.java

А тепер перейдемо до написання коду обробки натискань кнопок Java. По суті, все зводиться до того, що нам необхідно знайти id кнопок і текстового поля, навішувати на них слухачі кліків по кнопках і додати функціонал установки тексту в дане текстове поле.

package com.evileg.javabuttons;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {

    TextView textView1;
    Button okButton;
    Button cancelButton;

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

        // Найдём View элементы
        textView1 = findViewById(R.id.textView1);
        okButton = findViewById(R.id.OkButton);
        cancelButton = findViewById(R.id.Cancelbutton);

        // Создадим обработчик нажатия кнопок OK
        View.OnClickListener onClickListenerOkBtn = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                textView1.setText("OK Button is pressed");
            }
        };

        // Создадим обработчик нажатия кнопок Cancel
        View.OnClickListener onClickListenerCancelBtn = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                textView1.setText("Cancel Button is pressed");
            }
        };

        // Установим обработчики кликов на кнопки
        okButton.setOnClickListener(onClickListenerOkBtn);
        cancelButton.setOnClickListener(onClickListenerCancelBtn);
    }
}

Qt QML

У проекті Qt QML я модифікую три файли... але не лякайтеся так, модифікації не будуть такими глобальними, як написання повноцінних класів і шаблону верстки, як це було в додатку на Java.

QMLButtons.pro

По-перше включимо підтримку модуля quickcontrols2 у проектному файлі, що дозволить включити стиль Material Design.

QT += quick quickcontrols2

main.cpp

По-друге включимо сам Material Design. Для цього потрібно додати всього два рядки до функції main.

Перша

#include <QQuickStyle>

Друга

QQuickStyle::setStyle("Material");

Вийде наступний код

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickStyle>

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    QQuickStyle::setStyle("Material");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

Обов'язково включайте підтримку Material Design до ініціалізації QQmlApplicationEngine, - це C++ і тут важлива послідовність виклику методів і функцій.

main.qml

А тепер подивимося на те, як отримати таку ж верстку програми, як і в Java і при цьому відразу ж зробити обробку натискань на кнопки, яке до речі написано в даному випадку в один рядок.

import QtQuick 2.10
import QtQuick.Window 2.10
import QtQuick.Controls 2.3
import QtQuick.Controls.Material 2.1

ApplicationWindow {
    visible: true
    width: 360
    height: 520
    title: qsTr("QML Buttons")

    Text {
        id: text_1
        text: qsTr("Press Button")

        anchors {
            top: parent.top
            topMargin: 32
            horizontalCenter: parent.horizontalCenter
        }
    }

    Button {
        anchors {
            left: parent.left
            bottom: parent.bottom
            right: parent.horizontalCenter
            margins: 8
        }

        text: qsTr("Ok")
        // Обработка нажатия кнопки
        onClicked: text_1.text = qsTr("OK Button is Pressed")
    }

    Button {
        anchors {
            right: parent.right
            bottom: parent.bottom
            left: parent.horizontalCenter
            margins: 8
        }

        text: qsTr("Cancel")
        // Обработка нажатия кнопки
        onClicked: text_1.text = qsTr("Cancel Button is Pressed")
    }
}

Вже помітили, що код у цьому випадку чистіший? Та й його значно менше. Звичайно, ми дістанемося і до таких місць, де виграватиме Java, але саме в цьому прикладі поки що трохи простіше виглядає код на QML.

Вам це подобається? Поділіться в соціальних мережах!

СГ
  • 01 грудня 2019 р. 19:58

Здравствуйте Евгений!Просматривая уроки от разных авторов,заметил,что многие не используют QT дизайнер.Создают всё на Qml.Или мне показалось,что так лучше для разработки.Сам попробовал пользоваться дизайнером при разработке под Android-не всегда корректно отображается картинка на устройстве.

Evgenii Legotckoi
  • 01 грудня 2019 р. 22:21

Добрый день, Слава!
На тот момент, когда лично я занялся QML, там всё было довольно криво реализовано в дизайнере, а многие вещи вовсе отсутствовали. Поэтому мне проще было сделать вёрстку вручную на QML. Тем более, что qml.ui файлы добавляют "дополнительный код", который скрывает некоторую функциональность и приходится дописывать alias и сигналы в самом ui файле, которые при дальнейшем открытии qml.ui в дизайнере могут быть удалены или переписаны. Это добавляет некоторое неудобство. Поэтому я предпочитаю писать код вручную, тем более, что он не добавляет так много вёрсточного кода обычно, как я если бы тоже самое реализовывалось на классических виджетах. С того времени, конечно, много воды утекло, и что-то возможно стало гораздо лучше, но времени разбираться в этом просто нет.

СГ
  • 01 грудня 2019 р. 23:07

Спасибо Евгений! Я посмотрел ваши уроки по Java-Qml.Хотел найти ответ на вопрос-ориентация экрана телефона.В java если я не ошибаюсь это прописывается в манифесте
(import android.content.pm.ActivityInfo;

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);или portrait

А как и где это прописывается в Qml? Или у вас есть урок,тогда посмотрю?

Evgenii Legotckoi
  • 01 грудня 2019 р. 23:15

Добрый день.
Также в манифест пишите. Вот статья про манифест для Android
На сайте часть статей по QML находятся в разделе QML, часть в разделе Android.
Я QMLем балуюсь по большей части, так что 50/50 смогу ответить на некоторые вопросы, но можете задавать вопросы на форуме . Кроме меня там уже много опытных программистов, которые могу подсобить, если обратят внимание на вопрос.

СГ
  • 01 грудня 2019 р. 23:29

Спасибо большое!

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up