Arrow
Arrow9 марта 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
  • 9 марта 2018 г. 12:40

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

    Evgenii Legotckoi
    • 11 марта 2018 г. 9: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 г. 9: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 г. 6: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 г. 9: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 г. 3:37

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

                                    Evgenii Legotckoi
                                    • 19 марта 2018 г. 5:10

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

                                      Комментарии

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

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

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

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

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

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

                                      • Результат:20баллов,
                                      • Очки рейтинга-10
                                      Последние комментарии
                                      i
                                      innorwall14 ноября 2024 г. 11:42
                                      Как Копировать Файлы в Linux If only females relatives with DZ offspring were considered these percentages were 23 order priligy online uk
                                      i
                                      innorwall14 ноября 2024 г. 9:09
                                      Qt/C++ - Урок 068. Hello World с использованием системы сборки CMAKE в CLion ditropan pristiq dosing With the Yankees leading, 4 3, Rivera jogged in from the bullpen to a standing ovation as he prepared for his final appearance in Chicago buy priligy pakistan
                                      i
                                      innorwall14 ноября 2024 г. 4:05
                                      EVILEG-CORE. Использование Google reCAPTCHA 2001; 98 29 34 priligy buy
                                      i
                                      innorwall14 ноября 2024 г. 4:00
                                      PyQt5 - Урок 007. Работаем с QML QtQuick (Сигналы и слоты) priligy 30mg Am J Obstet Gynecol 171 1488 505
                                      Сейчас обсуждают на форуме
                                      i
                                      innorwall14 ноября 2024 г. 3:39
                                      добавить qlineseries в функции priligy amazon canada 93 GREB1 protein GREB1 AB011147 6
                                      i
                                      innorwall11 ноября 2024 г. 10:55
                                      Всё ещё разбираюсь с кешем. priligy walgreens levitra dulcolax carbs The third ring was found to be made up of ultra relativistic electrons, which are also present in both the outer and inner rings
                                      9
                                      9Anonim25 октября 2024 г. 9:10
                                      Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…
                                      ИМ
                                      Игорь Максимов3 октября 2024 г. 4:05
                                      Реализация навигации по разделам Спасибо Евгений!

                                      Следите за нами в социальных сетях