Arrow
Arrow09 березня 2018 р. 12:35

Связь интерфейса QML с C++

QML C++, интерфейс

Первый раз пытаюсь работать с QML.

Пытаюсь написать самое простое, что только есть - сложение двух чисел.

Не выходит ничего. Делаю так.

Код:

Файл main.cpp:

 
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include "myclass.h"

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

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    qputenv("QT_LABS_CONTROLS_STYLE", QVariant("Material").toByteArray());

    const QUrl mainQml(QStringLiteral("qrc:/main.qml"));

    const QMetaObject::Connection connection = QObject::connect(
                &engine, &QQmlApplicationEngine::objectCreated,
                &app, [&](QObject *object, const QUrl &url) {
            if (url != mainQml)
            return;

            if (!object)
            app.exit(-1);
            else
            QObject::disconnect(connection);
}, Qt::QueuedConnection);

    engine.load(mainQml);

    QObject* root = engine.rootObjects()[0];
    MyClass(root);
    engine.rootContext()->setContextProperty("myClass", &myClass);

    return app.exec();
}

В файле myclass.h:
 
public:
    Q_INVOKABLE void func();
В файле myclass.cpp:
 
void MyClass::func()
{
    QObject* numberX = viewer->findChild<QObject*>("numberX");
    QObject* numberY = viewer->findChild<QObject*>("numberY");

    QObject* resultLabel = viewer->findChild<QObject*>("resultLabel");

    QString str1 = (numberX->property("text")).toString();
    QString str2 = (numberY->property("text")).toString();

    int c = str1.toInt() + str2.toInt();

    resultLabel->setProperty("text", str1 + " + " + str2 + " = " + QString::number(c));
}
Файл main.qml:
 
import QtQuick 2.7
import QtQuick.Controls 1.5

ApplicationWindow {
    visible: true
    width: 250
    height: 230
    title: qsTr("QmlTest")

    Label {
        id: label
        x: 23
        y: 9
        text: qsTr("Сумма двух чисел")
    }

    Label {
        id: label1
        x: 23
        y: 48
        text: qsTr("Число 1:")
    }

    Label {
        id: label2
        x: 23
        y: 97
        text: qsTr("Число 2:")
    }

    Label {
        id: resultLabel
        objectName: resultLabel
        x: 23
        y: 140
        width: 70
        height: 20
        text: qsTr("Результат:")
    }

    TextField {
        id: numberY
        objectName: numberY
        x: 99
        y: 92
        width: 130
        height: 30
    }

    TextField {
        id: numberX
        objectName: numberY
        x: 99
        y: 40
        width: 130
        height: 30
    }

    Button {
        id: calckBtn
        x: 23
        y: 183
        width: 80
        text: qsTr("Расчет")
    }

    Connections {
        target: calckBtn
        onClicked: myClass.func()
    }

    Connections {
        target: exitBtn
        onClicked: Qt.quit()
    }

    Button {
        id: exitBtn
        x: 149
        y: 183
        width: 80
        text: qsTr("Exit")
    }
}
Что я делаю не так. В примере который смотрел реализовано так.

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

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

18
Arrow
  • 09 березня 2018 р. 12:40

В файле myclass.h: QObject *viewer;

    Evgenii Legotckoi
    • 11 березня 2018 р. 09:33

    setContextProperty нужно использовать до загрузки qml файла в движок.

    Посмотрите пример в этой статье

    Зачем вот всё это? В каком примере Вы всё это увидели?
    const QMetaObject::Connection connection = QObject::connect(
                    &engine, &QQmlApplicationEngine::objectCreated,
                    &app, [&](QObject *object, const QUrl &url) {
                if (url != mainQml)
                return;
    
                if (!object)
                app.exit(-1);
                else
                QObject::disconnect(connection);
    }, Qt::QueuedConnection);
    Нет никакого смысла лезть в мета-объектную систему там, где это не нужно.
      Arrow
      • 11 березня 2018 р. 10:27

      Этот код QtCreator сам сгенерировал.
      Сделал как в примере, приложение вообще не запускается, пишет:

      ASSERT failure in QList<T>::operator[]: "index out of range", file /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h, line 545
        Evgenii Legotckoi
        • 11 березня 2018 р. 11:26

        Первый раз вижу, чтобы QtCreator генерировал код с MetaObject::Connection. Какой именно проект запускали?

        Специально создал пустой проект с QML и вижу, что там ничего подобного не создаётся.
        #include <QGuiApplication>
        #include <QQmlApplicationEngine>
        
        int main(int argc, char *argv[])
        {
            QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        
            QGuiApplication app(argc, argv);
        
            QQmlApplicationEngine engine;
            engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
            if (engine.rootObjects().isEmpty())
                return -1;
        
            return app.exec();
        }
        
        Что касается ошибки, то выход за пределы массива, делаете обращение за пределы массива. При этом не вижу абсолютно никаких векторов в коде.
        Включайте в режиме дебага и смотрите, где вылетает. В любом случае где-то делаете обращение к объектам раньше, чем они инициализованы.
          Arrow
          • 11 березня 2018 р. 11:36

          Проект на QtQuick (не пустой) креатор последний


            Evgenii Legotckoi
            • 11 березня 2018 р. 11:50

            Ок, скачал бету, проверил. Действительно, есть подключение мета-объектной системы. У меня вопрос: Зачем Вы используете Бету креатора?
            Впрочем, ваше право - сидеть на нестабильном софте.


            Касательно выхода за пределы массива, рекомендация остаётся той же самой, пройдитесь через дебагер. В представленном коде не вижу ничего такого, что могло бы быть ошибочно, кроме того, что я сказал по поводу установки контекста до загрузки qml файла в движок. Сначала установить контекст, потом грузить файл qml в движок.

              Arrow
              • 11 березня 2018 р. 12:13

              Я в нем только проект генерировал. Сам я сижу на CLion.


                Arrow
                • 12 березня 2018 р. 14:31

                Такая конструкция не работает:

                QObject* numberX = this->findChild<QObject*>("numberX");

                Получается такой результат:

                QObject(0x0)

                Есть ли возможность заменить эту конструкцию, я пока не смог найти ответа.



                  Evgenii Legotckoi
                  • 13 березня 2018 р. 09:59

                  Здесь Вы выбрали неправильного парента, в котором пытаетесь найти потомков, полагаю, что те объекты из QML слоя. Можете найти потомков через root объекты в QQmlAplicationEngine, метода rootObjects.

                  либо создавайте Q_INVOKABLE методы через которые сможете передать указатель на объект из QML в C++. Когда создаёте Q_INVOKABLE метод с указателем на QObject , то в этот метод в QML слое можно передавать id объекта в QML .
                    Arrow
                    • 13 березня 2018 р. 10:30

                    А если не сложно, можно пример передачи id объекта QML. Именно как это написать в main.qml.

                      Evgenii Legotckoi
                      • 13 березня 2018 р. 11:25
                      • (відредаговано)
                      • Відповідь була позначена як рішення.

                      Да, конечно.


                      Вот у вас зарегистрирован некий класс в C++ в качестве контекста в QML и он имеет метод, который принимает указатель на QObject класс в качестве аргумента.

                      #ifndef APPCORE_H
                      #define APPCORE_H
                      
                      #include <QObject>
                      
                      class AppCore : public QObject
                      {
                          Q_OBJECT
                          using BaseClass = QObject;
                      public:
                          explicit AppCore(QObject *parent = nullptr);
                          // Метод, который принимает некоторый указатель на QObject
                          Q_INVOKABLE void receiveFromQml(QObject* someObject);
                      
                      signals:
                      
                      public slots:
                      };
                      
                      #endif // APPCORE_H
                      Реализация класса
                      #include "AppCore.h"
                      
                      #include <QDebug>
                      
                      AppCore::AppCore(QObject *parent) :
                          BaseClass(parent)
                      {
                      
                      }
                      
                      void AppCore::receiveFromQml(QObject *someObject)
                      {
                          someObject->setProperty("text", "Hello world");
                      }
                      
                      Как он зарегистрирован в QML
                      #include <QGuiApplication>
                      #include <QQmlApplicationEngine>
                      #include <QQmlContext>
                      #include "AppCore.h"
                      
                      int main(int argc, char *argv[])
                      {
                          QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
                      
                          QGuiApplication app(argc, argv);
                      
                          QQmlApplicationEngine engine;
                          AppCore appCore;
                          QQmlContext* context = engine.rootContext();
                          context->setContextProperty("appCore", &appCore);
                      
                          engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                          if (engine.rootObjects().isEmpty())
                              return -1;
                      
                          return app.exec();
                      }
                      
                      И далее, как это работает в QML
                      import QtQuick 2.9
                      import QtQuick.Window 2.2
                      import QtQuick.Controls 2.2
                      
                      Window {
                          visible: true
                          width: 640
                          height: 480
                          title: qsTr("Hello World")
                      
                          Text {
                              id: text
                              text: qsTr("Empty Text")
                              anchors.centerIn: parent
                          }
                      
                          Button {
                              text: qsTr("Press Me")
                              anchors.top: text.bottom
                              anchors.topMargin: 20
                              anchors.horizontalCenter: parent.horizontalCenter
                      
                              onClicked: {
                                  // Просто передаём id текстового поля. В данном случае будет передан указатель на QObject
                                  appCore.receiveFromQml(text)
                              }
                          }
                      }
                      
                      В результате работы этого кода, текст в текстовом поле будет заменён.
                        Arrow
                        • 13 березня 2018 р. 11:30

                        Огромное спасибо!!!

                          Arrow
                          • 14 березня 2018 р. 06:25

                          Проверил в Linux Debian 9 64bit (Qt 5.10), компилятор Clang - все работает.

                          В Windows 7 64 bit (Qt5.10), компилятор Clang - Запускается, но при появлении окна вылетает: Process finished with exit code -1073741819 (0xC0000005).

                          PS. Если интересно могу выложить почти "универсальный" CMakeLists для работы с Qt.
                            Evgenii Legotckoi
                            • 14 березня 2018 р. 09:30
                            • (відредаговано)

                            Могу предположить только то, что там может быть баг, как вариант под Windows стоит попробовать собрать с помощью MSVC.


                            Любой CMakeLists для Qt может пригодиться, по крайней мере кому-то в будущем точно.
                              Arrow
                              • 14 березня 2018 р. 10:23
                              CMakeLists.txt:


                              cmake_minimum_required(VERSION 3.1)
                              
                              # Имя проекта ProjName
                              project(ProjName LANGUAGES CXX)
                              
                              # Искать подключаемые файлы в директории сборки
                              set(CMAKE_INCLUDE_CURRENT_DIR ON)
                              
                              set(CMAKE_AUTOMOC ON)
                              set(CMAKE_AUTOUIC ON)
                              set(CMAKE_AUTORCC ON)
                              
                              # C++11
                              set(CMAKE_CXX_STANDARD 11)
                              set(CMAKE_CXX_STANDARD_REQUIRED ON)
                              
                              # Компилятор Clang для C
                              SET (CMAKE_C_COMPILER             clang)
                              # Флаги
                              SET (CMAKE_C_FLAGS                "-Wall -std=c99")
                              SET (CMAKE_C_FLAGS_DEBUG          "-g")
                              SET (CMAKE_C_FLAGS_MINSIZEREL     "-Os -DNDEBUG")
                              SET (CMAKE_C_FLAGS_RELEASE        "-O3 -DNDEBUG")
                              SET (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g")
                              
                              # Компилятор Clang для C++
                              SET (CMAKE_CXX_COMPILER clang++)
                              # Флаги
                              set(CMAKE_CXX_FLAGS                "-Wall -std=c++11")
                              set(CMAKE_CXX_FLAGS_DEBUG          "-O0 -g")
                              set(CMAKE_CXX_FLAGS_MINSIZEREL     "-Os -DNDEBUG")
                              set(CMAKE_CXX_FLAGS_RELEASE        "-O3 -DNDEBUG")
                              set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
                              
                              # Авто поиск *.cpp, *.h, *.ui, *.qrc в директории проекта (без поддиректорий)
                              FILE(GLOB SOURCE_FILES ${PROJECT_SOURCE_DIR}/*.cpp)
                              FILE(GLOB HEADER_FILES ${PROJECT_SOURCE_DIR}/*.h)
                              FILE(GLOB UI_SRC_FILES ${PROJECT_SOURCE_DIR}/*.ui)
                              FILE(GLOB UI_QRCS ${PROJECT_SOURCE_DIR}/*.qrc)
                              
                              # Иконка приложения для Windows
                              FILE(GLOB ICON_RCS ${PROJECT_SOURCE_DIR}/*.rc)
                              
                              # Модули Qt (Widgets, QtGui, QtCore, QtPrintSupport)
                              find_package(Qt5 COMPONENTS Widgets PrintSupport REQUIRED)
                              
                              # Ресурсы *.qrc
                              qt5_add_resources(UI_RESOURCES_RCC ${UI_QRCS})
                              
                              # Папка для релиз версии исп. файла
                              if(CMAKE_BUILD_TYPE STREQUAL "Release")
                                  if(WIN32)
                                      set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/Winows)
                                  elseif(UNIX)
                                      set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/Linux)
                                  endif()
                              endif()
                              
                              # Исп. файл
                              if(WIN32)
                                  add_executable(${PROJECT_NAME} WIN32 ${SOURCE_FILES} ${HEADER_FILES}
                                      ${UI_SRC_FILES} ${UI_RESOURCES_RCC} ${ICON_RCS})
                              
                                  # Qt модули
                                  target_link_libraries(${PROJECT_NAME} Qt5::Widgets Qt5::PrintSupport)    
                              else()
                                  add_executable(${PROJECT_NAME} ${SOURCE_FILES} ${HEADER_FILES}
                                      ${UI_SRC_FILES} ${UI_RESOURCES_RCC})
                              
                                  target_link_libraries(${PROJECT_NAME} Qt5::Widgets Qt5::PrintSupport)
                              endif()
                              
                              Файл для иконки приложения logo.rc:

                              IDI_ICON1 ICON DISCARDABLE "ProjICO.ico"

                                Arrow
                                • 14 березня 2018 р. 10:25

                                Как внести информацию о компании версии программы и т.д. не нашел, если кто знает как пишите :)

                                  Arrow
                                  • 19 березня 2018 р. 03:37

                                  Проблема с запуском наблюдается только при компиляции на Windows 64 bit версии программы, 32 bit работает без проблем.

                                    Evgenii Legotckoi
                                    • 19 березня 2018 р. 05:10

                                    Тогда на MSVC собирайте, а не на Clang. С MSVC я проблем не наблюдал, может, конечно, что-то всплыть и там, но ... другого варианта всё равно на данный момент нет.

                                      Коментарі

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

                                      C++ - Тест 004. Указатели, Массивы и Циклы

                                      • Результат:50бали,
                                      • Рейтинг балів-4
                                      m
                                      • molni99
                                      • 26 жовтня 2024 р. 11:37

                                      C++ - Тест 004. Указатели, Массивы и Циклы

                                      • Результат:80бали,
                                      • Рейтинг балів4
                                      m
                                      • molni99
                                      • 26 жовтня 2024 р. 11:29

                                      C++ - Тест 004. Указатели, Массивы и Циклы

                                      • Результат:20бали,
                                      • Рейтинг балів-10
                                      Останні коментарі
                                      ИМ
                                      Игорь Максимов22 листопада 2024 р. 22:51
                                      Django - Підручник 017. Налаштуйте сторінку входу до Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
                                      Evgenii Legotckoi
                                      Evgenii Legotckoi01 листопада 2024 р. 00:37
                                      Django - Урок 064. Як написати розширення для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
                                      A
                                      ALO1ZE19 жовтня 2024 р. 18:19
                                      Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
                                      ИМ
                                      Игорь Максимов05 жовтня 2024 р. 17:51
                                      Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
                                      d
                                      dblas505 липня 2024 р. 21:02
                                      QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                                      Тепер обговоріть на форумі
                                      Evgenii Legotckoi
                                      Evgenii Legotckoi25 червня 2024 р. 01:11
                                      добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
                                      t
                                      tonypeachey115 листопада 2024 р. 17:04
                                      google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
                                      NSProject
                                      NSProject04 червня 2022 р. 13:49
                                      Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
                                      9
                                      9Anonim25 жовтня 2024 р. 19:10
                                      Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

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