Evgenii Legotckoi
27 февраля 2018 г. 13:40

Android. Java vs 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

Файл вёрстки нашей главной activity. Для того, чтобы поместить обе кнопки в нижнюю часть экрана, понадобилось использовать Layout в горизонтальной ориентации, что примечательно, в QML вам это не понадобится для подобного вида вёрстки кнопок в данном примере. Поскольку в QML используются якоря , которые сходны по принципу с работой свойств layout_constraint , но на мой взгляд несколько более гибкие.

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. tools:context="com.evileg.javabuttons.MainActivity">
  8.  
  9. <TextView
  10. android:id="@+id/textView1"
  11. android:layout_width="wrap_content"
  12. android:layout_height="wrap_content"
  13. android:layout_marginTop="32dp"
  14. android:text="Press Button"
  15. app:layout_constraintEnd_toEndOf="parent"
  16. app:layout_constraintHorizontal_bias="0.5"
  17. app:layout_constraintStart_toStartOf="parent"
  18. app:layout_constraintTop_toTopOf="parent" />
  19.  
  20. <LinearLayout
  21. android:layout_width="match_parent"
  22. android:layout_height="wrap_content"
  23. android:layout_marginBottom="8dp"
  24. android:layout_marginEnd="8dp"
  25. android:layout_marginStart="8dp"
  26. android:orientation="horizontal"
  27. android:gravity="center_horizontal"
  28. android:weightSum="2"
  29. app:layout_constraintBottom_toBottomOf="parent"
  30. app:layout_constraintEnd_toEndOf="parent"
  31. app:layout_constraintStart_toStartOf="parent">
  32.  
  33. <Button
  34. android:id="@+id/OkButton"
  35. android:layout_width="0dp"
  36. android:layout_height="wrap_content"
  37. android:text="Ok"
  38. android:layout_weight="1"/>
  39.  
  40. <Button
  41. android:id="@+id/Cancelbutton"
  42. android:layout_width="0dp"
  43. android:layout_height="wrap_content"
  44. android:text="Cancel"
  45. android:layout_weight="1"/>
  46. </LinearLayout>
  47.  
  48. </android.support.constraint.ConstraintLayout>

MainActivity.java

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

  1. package com.evileg.javabuttons;
  2.  
  3. import android.app.Activity;
  4. import android.os.Bundle;
  5. import android.view.View;
  6. import android.view.Window;
  7. import android.widget.Button;
  8. import android.widget.TextView;
  9.  
  10. public class MainActivity extends Activity {
  11.  
  12. TextView textView1;
  13. Button okButton;
  14. Button cancelButton;
  15.  
  16. @Override
  17. protected void onCreate(Bundle savedInstanceState) {
  18. super.onCreate(savedInstanceState);
  19. this.requestWindowFeature(Window.FEATURE_NO_TITLE);
  20. setContentView(R.layout.activity_main);
  21.  
  22. // Найдём View элементы
  23. textView1 = findViewById(R.id.textView1);
  24. okButton = findViewById(R.id.OkButton);
  25. cancelButton = findViewById(R.id.Cancelbutton);
  26.  
  27. // Создадим обработчик нажатия кнопок OK
  28. View.OnClickListener onClickListenerOkBtn = new View.OnClickListener() {
  29. @Override
  30. public void onClick(View v) {
  31. textView1.setText("OK Button is pressed");
  32. }
  33. };
  34.  
  35. // Создадим обработчик нажатия кнопок Cancel
  36. View.OnClickListener onClickListenerCancelBtn = new View.OnClickListener() {
  37. @Override
  38. public void onClick(View v) {
  39. textView1.setText("Cancel Button is pressed");
  40. }
  41. };
  42.  
  43. // Установим обработчики кликов на кнопки
  44. okButton.setOnClickListener(onClickListenerOkBtn);
  45. cancelButton.setOnClickListener(onClickListenerCancelBtn);
  46. }
  47. }

Qt QML

В проекте на Qt QML я модифицирую три файла... но не пугайтесь так, модификации не будут такими глобальными, как написание полноценных классов и шаблона вёрстки, как это было в приложении на Java.

QMLButtons.pro

Во-первых включим поддержку модуля quickcontrols2 в проектном файле, что позволит включить стиль Material Design.

  1. QT += quick quickcontrols2

main.cpp

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

Первая

  1. #include <QQuickStyle>

Вторая

  1. QQuickStyle::setStyle("Material");

Получится следующий код

  1. #include <QGuiApplication>
  2. #include <QQmlApplicationEngine>
  3. #include <QQuickStyle>
  4.  
  5. int main(int argc, char *argv[])
  6. {
  7. QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
  8.  
  9. QGuiApplication app(argc, argv);
  10.  
  11. QQuickStyle::setStyle("Material");
  12.  
  13. QQmlApplicationEngine engine;
  14. engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
  15. if (engine.rootObjects().isEmpty())
  16. return -1;
  17.  
  18. return app.exec();
  19. }

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

main.qml

А теперь посмотрим на то, как получить такую же вёрстку приложения, как и в Java и при этом сразу же сделать обработку нажатий по кнопкам, которое кстати написано в данном случае в одну строку.

  1. import QtQuick 2.10
  2. import QtQuick.Window 2.10
  3. import QtQuick.Controls 2.3
  4. import QtQuick.Controls.Material 2.1
  5.  
  6. ApplicationWindow {
  7. visible: true
  8. width: 360
  9. height: 520
  10. title: qsTr("QML Buttons")
  11.  
  12. Text {
  13. id: text_1
  14. text: qsTr("Press Button")
  15.  
  16. anchors {
  17. top: parent.top
  18. topMargin: 32
  19. horizontalCenter: parent.horizontalCenter
  20. }
  21. }
  22.  
  23. Button {
  24. anchors {
  25. left: parent.left
  26. bottom: parent.bottom
  27. right: parent.horizontalCenter
  28. margins: 8
  29. }
  30.  
  31. text: qsTr("Ok")
  32. // Обработка нажатия кнопки
  33. onClicked: text_1.text = qsTr("OK Button is Pressed")
  34. }
  35.  
  36. Button {
  37. anchors {
  38. right: parent.right
  39. bottom: parent.bottom
  40. left: parent.horizontalCenter
  41. margins: 8
  42. }
  43.  
  44. text: qsTr("Cancel")
  45. // Обработка нажатия кнопки
  46. onClicked: text_1.text = qsTr("Cancel Button is Pressed")
  47. }
  48. }

Уже заметили, что код в данном случае чище? Да и его значительно меньше. Конечно, мы доберёмся и до таких мест, где будет выигрывать Java, но конкретно в данном примере пока что несколько проще выглядит код на QML.

Вам это нравится? Поделитесь в социальных сетях!

СГ
  • 1 декабря 2019 г. 19:58

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

Evgenii Legotckoi
  • 1 декабря 2019 г. 22:21

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

СГ
  • 1 декабря 2019 г. 23:07

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

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);или portrait

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

Evgenii Legotckoi
  • 1 декабря 2019 г. 23:15

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

СГ
  • 1 декабря 2019 г. 23:29

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

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь