Evgenii Legotckoi
Evgenii Legotckoi02 березня 2018 р. 13:53

Android. Java проти Qt QML - Підручник 004. Створення меню на панелі дій з підменю

Отже, продовжуємо реалізовувати однаковий функціонал у додатках під Android із двох принципово різних світів. А саме на традиційній Java і менш поширеній Qt QML C++.

На цей раз реалізуємо меню в ActionBar активіті. Зазначу, що ActionBar для варіанта з QML доведеться писати самостійно, оскільки такого елемента Qt QML немає, але він реалізується через компонент ToolBar. Оскільки цей момент був описаний в уроці про Hello World , то в даному уроці ретельно зупинятися на ньому не будемо, тільки винесемо ActionBar в окремий файл QML, зробивши його окремим типом QML і додамо до нього іконку меню, за натисканням на яку викликатимемо меню.

Меню буде наступною структурою:

  • Інформація
  • Перший
  • Другий
  • Про

У центрі вікна програми повинен бути текст, який замінюватиметься іншим текстом при натисканні наступних пунктів меню

  • Спочатку
  • Другий
  • Про

Зовнішній вигляд меню на Java

Перший рівень

Другий рівень

Зовнішній вигляд меню на Qt QML

Перший рівень

Другий рівень

Реалізація JAVA

menu.xml

Для верстки меню необхідно створити XML файл, який розташовуватиметься в ресурсному каталозі menu. Так і назвемо його menu.xml

Тут все досить просто, є невелика верстка з назвами пунктів меню, вкладеними елементами та id, якими можна буде звернутися до даних пунктів з Java коду.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/informationItem"
        android:title="Information">
        <menu>
            <item
                android:id="@+id/firstInfoItem"
                android:title="First" />
            <item
                android:id="@+id/secondInfoItem"
                android:title="Second" />
        </menu>
    </item>
    <item
        android:id="@+id/aboutItem"
        android:title="About" />
</menu>

activity_main.xml

Далі йде верстка самої активіті, яка в даному випадку створена за умовчанням.

<?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.javamenu.MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

MainActivity.java

А тепер потрібно ініціалізувати всі компоненти меню та навішувати на них обробник події кліка.

package com.evileg.javamenu;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;

public class MainActivity extends Activity {

    // Объявим объекты всех пунктов меню
    MenuItem aboutItem;
    MenuItem firstInfoItem;
    MenuItem secondInfoItem;

    // А также текстового поля, в которое будем устанавливать текст
    TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView); // найдём данное текстовое поле в ресурсах
    }

    // Создадим обработчики пунктов меню
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu, menu);

        // Найдём все элементы пунктов меню
        aboutItem = menu.findItem(R.id.aboutItem);
        firstInfoItem = menu.findItem(R.id.firstInfoItem);
        secondInfoItem = menu.findItem(R.id.secondInfoItem);

        // Создадим обработчик кликов по пунктам меню
        MenuItem.OnMenuItemClickListener onMenuClickListener = new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.aboutItem:
                        textView.setText("About Menu Item is pressed");
                        break;
                    case R.id.firstInfoItem:
                        textView.setText("First Info Item is pressed");
                        break;
                    case R.id.secondInfoItem:
                        textView.setText("Second Info Item is pressed");
                        break;
                }
                return true;
            }
        };

        // Установим этот обработчик на пункты меню
        aboutItem.setOnMenuItemClickListener(onMenuClickListener);
        firstInfoItem.setOnMenuItemClickListener(onMenuClickListener);
        secondInfoItem.setOnMenuItemClickListener(onMenuClickListener);

        return true;
    }
}

Реалізація Qt QML

ActionBar.qml

Я створив спеціальний тип ActionBar в окремому файлі QML, щоб виділити його з основного файлу main.qml. Це дозволить відокремити цей код від решти корисної частини коду, яка має показати відмінність реалізацій меню на Java та Qt QML. Також цей ActionBar буде використовуватися в наступних статтях.

Зверніть увагу на сигнал menuClicked , цей сигнал буде викликатись у ActionBar, коли користувач натисне пальцем на MouseArea, яка відповідає за клік по нашій кастомній кнопці меню. За цим сигналом буде відкрито меню, розташоване у файлі main.qml

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

ToolBar {
    id: root
    height: 48

    signal menuClicked() // Сигнал, который сообщит о клике по кнопке меню

    Rectangle {
        anchors.fill: parent
        color: "#080808"

        Image {
            id: ico
            height: 36
            width: 36
            anchors {
                left: parent.left
                leftMargin: 10
                top: parent.top
                topMargin: 6
            }
            source: "qrc:/icons/ic_launcher.png"
        }


        Text {
            anchors {
                verticalCenter: parent.verticalCenter
                left: ico.right
                leftMargin: 4
            }

            text: qsTr("QMLMenu")
            font.pixelSize: 18
            color: "white"
        }

        // Начало реализации кнопки меню
        Rectangle {
            width: height
            color: menuArea.pressed ? "#55ffffff" : "transparent"
            anchors {
                top: parent.top
                right: parent.right
                bottom: parent.bottom
            }

            Image {
                id: menuIcon
                height: 36
                width: 36
                anchors {
                    centerIn: parent
                }

                source: "qrc:/icons/menu.png"
            }

            MouseArea {
                id: menuArea
                anchors.fill: parent
                onClicked: root.menuClicked()
            }
        }
        // конец реализации кнопки меню
    }
}

main.qml

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

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

ApplicationWindow {
    id: root
    visible: true
    width: 360
    height: 520
    title: qsTr("QML Menu")

    // Добавляем ActionBar в окно приложения
    header: ActionBar {
        onMenuClicked: actionBarMenu.open() // Открываем меню

        // Добавляем меню
        Menu {
            id: actionBarMenu
            // С указанием расположения, чтобы Menu выскакивало в том же месте,
            // что и в варианте с Java
            x: root.width
            y: 48
            Menu {
                title: qsTr("Information")
                Action {
                    text: qsTr("First")
                    // Обработка клика по меню
                    onTriggered: label.text = qsTr("First Info Item is pressed")
                }
                Action {
                    text: qsTr("Second")
                    onTriggered: label.text = qsTr("Second Info Item is pressed")
                }
            }
            Action {
                text: qsTr("About")
                onTriggered: label.text = qsTr("About Menu Item is pressed")
            }
        }
    }

    Label {
        id: label
        anchors.centerIn: parent
        text: qsTr("Hello World!")
        font.pixelSize: 14
    }
}

Висновок

Звичайно, є деяка різниця в реалізації меню за замовчуванням для Java і Qt QML, наприклад наявність заголовка підменю. Теоретично в QML це можна реалізувати за допомогою порожнього Action, який матиме title, буде трохи кастомізований і нічого не робитиме при кліку, але чи потрібно це?

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

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

Михаиллл
  • 09 липня 2019 р. 19:33
  • (відредаговано)

Добрый день.
Как в такое меню добавить картинку и просто лэйблы с текстом?
И скажите пожалуйста как связаны ActionBar.qml и main.qml?

Михаиллл
  • 10 липня 2019 р. 14:08
  • (відредаговано)

Превый файл скопировал, в другой qml вставил этот код, но меню не появляется

         ActionBar {
            onMenuClicked: actionBarMenu.open() // Открываем меню

            // Добавляем меню
            Menu {
                id: actionBarMenu
                // С указанием расположения, чтобы Menu выскакивало в том же месте,
                // что и в варианте с Java
                x: root.width
                y: 48
                Menu {
                    title: qsTr("Information")
                    Action {
                        text: qsTr("First")
                        // Обработка клика по меню
                        //onTriggered: label.text = qsTr("First Info Item is pressed")
                    }
                    Action {
                        text: qsTr("Second")
                        //onTriggered: label.text = qsTr("Second Info Item is pressed")
                    }
                }
                Action {
                    text: qsTr("About")
                    //onTriggered: label.text = qsTr("About Menu Item is pressed")
                }
            }
        }

Вот так работает

    Button {

        x: 5
        y: 5
        id:  menuButton
        text:  "Menu"
        onClicked:  myMenu.open()

    }

    Menu {
        id:  myMenu
        x: 5
        y: menuButton.height

        MenuItem {
            text:  "Мои данные"
            onClicked: console.log("Мои данные")
        }
        MenuItem {
            text:  "Чат"
            onClicked: console.log("Чат")
        }
        MenuItem {
            text:  "Видео"
            onClicked: console.log("Видео")
        }
        MenuItem {
            text:  "Контакты"
            onClicked: console.log("Контакты")
        }

    }
Evgenii Legotckoi
  • 11 липня 2019 р. 14:27
  • (відредаговано)

У объектов MenuItem есть свойства iconName и iconSource. В iconSource можно добавить иконку из ресурсов в проекте. Можете воспользоваться этим свойством и тогда у вас будут в пунктах меню и иконки и текст.

Коментарі

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

Qt - Тест 001. Сигналы и слоты

  • Результат:68бали,
  • Рейтинг балів-1
ЛС

C++ - Тест 001. Первая программа и типы данных

  • Результат:53бали,
  • Рейтинг балів-4
АА

C++ - Тест 001. Первая программа и типы данных

  • Результат:60бали,
  • Рейтинг балів-1
Останні коментарі
ИМ
Игорь Максимов05 жовтня 2024 р. 07:51
Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas505 липня 2024 р. 11:02
QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssr08 лютого 2024 р. 18:43
Qt Linux - Урок 001. Автозапуск програми Qt під Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий Кононенко05 лютого 2024 р. 01:50
Qt WinAPI - Урок 007. Робота з ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25 грудня 2023 р. 10:30
Boost - статичне зв&#39;язування в проекті CMake під Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
Тепер обговоріть на форумі
K
Keithfap13 жовтня 2024 р. 09:24
добавить qlineseries в функции North Symbol by Bubnov Ltd https://seven-elephants.com/en/categories/penthouse/ Искеле – жемчужина острова! Все факторы говорят про большой инвестиционный потенциал данного района как для …
ИМ
Игорь Максимов03 жовтня 2024 р. 04:05
Реализация навигации по разделам Спасибо Евгений!
JW
Jhon Wick01 жовтня 2024 р. 15:52
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Кирилл Гусарев27 вересня 2024 р. 09:09
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
F
Fynjy22 липня 2024 р. 04:15
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

Слідкуйте за нами в соціальних мережах