Arrow
ArrowMarch 9, 2018, 12:35 p.m.

Связь интерфейса 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")
    }
}
Что я делаю не так. В примере который смотрел реализовано так.

Все компилируется и запускается, но при нажатии на кнопку "Расчет" приложение вылетает.
We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

18
Arrow
  • March 9, 2018, 12:40 p.m.

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

    Evgenii Legotckoi
    • March 11, 2018, 9:33 a.m.

    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
      • March 11, 2018, 10:27 a.m.

      Этот код 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
        • March 11, 2018, 11:26 a.m.

        Первый раз вижу, чтобы 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
          • March 11, 2018, 11:36 a.m.

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


            Evgenii Legotckoi
            • March 11, 2018, 11:50 a.m.

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


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

              Arrow
              • March 11, 2018, 12:13 p.m.

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


                Arrow
                • March 12, 2018, 2:31 p.m.

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

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

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

                QObject(0x0)

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



                  Evgenii Legotckoi
                  • March 13, 2018, 9:59 a.m.

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

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

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

                      Evgenii Legotckoi
                      • March 13, 2018, 11:25 a.m.
                      • (edited)
                      • The answer was marked as a solution.

                      Да, конечно.


                      Вот у вас зарегистрирован некий класс в 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
                        • March 13, 2018, 11:30 a.m.

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

                          Arrow
                          • March 14, 2018, 6:25 a.m.

                          Проверил в 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
                            • March 14, 2018, 9:30 a.m.
                            • (edited)

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


                            Любой CMakeLists для Qt может пригодиться, по крайней мере кому-то в будущем точно.
                              Arrow
                              • March 14, 2018, 10:23 a.m.
                              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
                                • March 14, 2018, 10:25 a.m.

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

                                  Arrow
                                  • March 19, 2018, 3:37 a.m.

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

                                    Evgenii Legotckoi
                                    • March 19, 2018, 5:10 a.m.

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

                                      Comments

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

                                      C ++ - Test 004. Pointers, Arrays and Loops

                                      • Result:50points,
                                      • Rating points-4
                                      m

                                      C ++ - Test 004. Pointers, Arrays and Loops

                                      • Result:80points,
                                      • Rating points4
                                      m

                                      C ++ - Test 004. Pointers, Arrays and Loops

                                      • Result:20points,
                                      • Rating points-10
                                      Last comments
                                      ИМ
                                      Игорь МаксимовNov. 22, 2024, 10:51 p.m.
                                      Django - Tutorial 017. Customize the login page to Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
                                      Evgenii Legotckoi
                                      Evgenii LegotckoiNov. 1, 2024, 12:37 a.m.
                                      Django - Lesson 064. How to write a Python Markdown extension Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
                                      A
                                      ALO1ZEOct. 19, 2024, 6:19 p.m.
                                      Fb3 file reader on Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
                                      ИМ
                                      Игорь МаксимовOct. 5, 2024, 5:51 p.m.
                                      Django - Lesson 064. How to write a Python Markdown extension Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
                                      d
                                      dblas5July 5, 2024, 9:02 p.m.
                                      QML - Lesson 016. SQLite database and the working with it in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                                      Now discuss on the forum
                                      Evgenii Legotckoi
                                      Evgenii LegotckoiJune 25, 2024, 1:11 a.m.
                                      добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
                                      t
                                      tonypeachey1Nov. 15, 2024, 5:04 p.m.
                                      google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
                                      NSProject
                                      NSProjectJune 4, 2022, 1:49 p.m.
                                      Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
                                      9
                                      9AnonimOct. 25, 2024, 7:10 p.m.
                                      Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

                                      Follow us in social networks