Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. [SOLVED] Dynamic C++ objects in QML
Forum Updated to NodeBB v4.3 + New Features

[SOLVED] Dynamic C++ objects in QML

Scheduled Pinned Locked Moved QML and Qt Quick
4 Posts 2 Posters 3.2k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    Decessus
    wrote on last edited by
    #1

    Hello I was wondering if there were a way to dynamically pass a C++ object to QML for use outside of a connections element (say in a state). Currently I have a qml file animating a singular button.

    window.h
    @class Window : public QWidget
    {
    Q_OBJECT
    Q_PROPERTY(int viewHeight READ viewHeight SCRIPTABLE true NOTIFY rebindViewSize)
    Q_PROPERTY(int viewWidth READ viewWidth SCRIPTABLE true NOTIFY rebindViewSize)

    public:
    explicit Window(QWidget *parent = 0);
    ~Window();

    Q_INVOKABLE AnimatedButton* m_button;
    

    public slots:
    Q_INVOKABLE void setTitle(QString m_title) { setWindowTitle(m_title); }

    protected slots:
    virtual void resizeEvent(QResizeEvent event);
    void buttonPressing(AnimatedButton
    button);

    private:
    Ui::Window *ui;
    QGraphicsScene *scene;
    int viewHeight() const;
    int viewWidth() const;

    QDeclarativeEngine engine;
    QList<QDeclarativeComponent*> loadedPlugins;
    

    Q_SIGNALS:
    void finishedLoading();
    void rebindViewSize();
    void buttonPressed(AnimatedButton* button);
    };@

    window.cpp
    @Window::Window(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Window)
    {
    ui->setupUi(this);
    scene = new QGraphicsScene(this);
    QGraphicsWidget *widget = new QGraphicsWidget();
    QGraphicsGridLayout grid = new QGraphicsGridLayout(widget);
    scene->addItem(widget);
    QGraphicsView view = new QGraphicsView(scene);
    ui->verticalLayout->addWidget(view);
    m_button = new AnimatedButton();
    connect(m_button,SIGNAL(clicked(AnimatedButton
    )),this,SLOT(buttonPressing(AnimatedButton
    )));

    engine.rootContext()->setContextProperty(QString("Katana"),this);
    engine.rootContext()->setContextProperty(QString("iButton"),m_button);
    engine.addPluginPath(QApplication::applicationDirPath());
    //QDeclarativeContext
    
    // encapsulates a QML component definition
    QDeclarativeComponent component(&engine,QUrl(QString("qrc:/scripts/qml/Katana/main.qml")));
    
    // creates the graphics item for QML at the engine's root context
    QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create());
    
    if(item)
        scene->addItem(item);
    
    loadedPlugins.append(&component);
    
    view->setRenderHint(QPainter::Antialiasing,true);
    
    qDebug() << component.errors();
    
    this->setLayout(ui->verticalLayout);
    
    Q_EMIT finishedLoading();
    m_button->setVisible(true);
    scene->addItem(m_button);
    m_button->setGeometry(0,0,100,100);
    m_button->setZValue(100);
    //m_button->raise();
    

    }

    Window::~Window()
    {
    delete ui;
    }

    void Window::buttonPressing(AnimatedButton *button) {
    Q_EMIT buttonPressed(button);
    }

    int Window::viewHeight() const {
    return height() - 10;
    }

    int Window::viewWidth() const {
    return width() - 10;
    }

    void Window::resizeEvent(QResizeEvent *event) {
    emit rebindViewSize();
    }@

    main.qml
    @Rectangle {
    id: mainView
    width: Katana.viewWidth
    height: Katana.viewHeight
    color: "black"
    state: ""

    Connections {
        target: Katana
        onButtonPressed: {
            state = "clicking"
        }
    }
    
    Connections {
        target: Katana
        onRebindViewSize: {
            mainView.width = Katana.viewWidth
            mainView.height = Katana.viewHeight
    
        }
    }
    
    states: [
        State {
            name: "clicking"
            PropertyChanges { target: button; opacity: 0.6; yRotation: 360; }
        }
    
    ]
    
    transitions: [
        Transition {
             from: ""; to: "clicking"; reversible: true
             ParallelAnimation {
                 NumberAnimation { properties: "opacity,yRotation"; duration: 300; easing.type: Easing.InOutQuad }
             }
         }
    ]
    

    }@

    Now, if I had say 30 buttons in my view, I would be able to access which button has been clicked dynamically through the Connections element with the use of 'button', however, how would I be able to pass the object 'button' information to the appropriate state for use as the PropertyChange's target?

    1 Reply Last reply
    0
    • K Offline
      K Offline
      KA51O
      wrote on last edited by
      #2

      if you solved your problem how about you post your solution so other people who are experiencing the same problem can benefit from you ?

      1 Reply Last reply
      0
      • D Offline
        D Offline
        Decessus
        wrote on last edited by
        #3

        My apologies, I thought I had updated this thread again, obviously, that is not the case. This issue is only partly solved at this point.

        window.h
        @#ifndef WINDOW_H
        #define WINDOW_H

        #include <QWidget>
        #include <QPushButton>
        #include <QDebug>
        #include <QGraphicsScene>
        #include <QGraphicsWidget>
        #include <QGraphicsProxyWidget>
        #include <QGraphicsLinearLayout>
        #include <QGraphicsGridLayout>
        #include <QState>
        #include <QStateMachine>
        #include <QGraphicsView>
        #include <QStackedWidget>

        #include <QtDeclarative/QDeclarativeEngine>
        #include <QtDeclarative/QDeclarativeContext>
        #include <QtDeclarative/QDeclarativeComponent>
        #include <QtDeclarative/QDeclarativeItem>
        #include <QtDeclarative/QDeclarativeError>

        #include "gui/animatedbutton.h"

        namespace Ui {
        class Window;
        }

        class Window : public QWidget
        {
        Q_OBJECT
        Q_PROPERTY(int viewHeight READ viewHeight SCRIPTABLE true NOTIFY rebindViewSize)
        Q_PROPERTY(int viewWidth READ viewWidth SCRIPTABLE true NOTIFY rebindViewSize)

        public:
        explicit Window(QWidget *parent = 0);
        ~Window();

        Q_INVOKABLE AnimatedButton* m_button;
        

        public slots:
        Q_INVOKABLE void setTitle(QString m_title) { setWindowTitle(m_title); }

        protected slots:
        virtual void resizeEvent(QResizeEvent event);
        void buttonClicking(AnimatedButton
        button);
        void buttonPressing(AnimatedButton* button);
        void buttonReleasing(AnimatedButton* button);
        void buttonHoverIn(AnimatedButton* button,int originX,int originY);
        void buttonHoverOut(AnimatedButton* button,int originX,int originY);
        void buttonHoverMove(AnimatedButton* button,int originX,int originY);
        void setupQmlTypes();

        private:
        Ui::Window *ui;
        QGraphicsScene *scene;
        int viewHeight() const;
        int viewWidth() const;

        QDeclarativeEngine engine;
        QList<QDeclarativeComponent*> loadedPlugins;
        

        Q_SIGNALS:
        void finishedLoading();
        void rebindViewSize();
        void buttonClicked(AnimatedButton* button);
        void buttonPressed(AnimatedButton* button);
        void buttonReleased(AnimatedButton* button);
        void buttonRollOver(AnimatedButton* button,int originX,int originY);
        void buttonRollOut(AnimatedButton button,int originX,int originY);
        void buttonRolling(AnimatedButton
        button,int originX,int originY);
        };

        #endif // WINDOW_H@

        main.qml
        @import QtQuick 1.0

        Rectangle {
        id: mainView
        width: Katana.viewWidth
        height: Katana.viewHeight
        color: "black"
        state: ""

        property variant target_button: null;
        property variant event_x: null;
        property variant event_y: null;
        
        Connections {
            target: Katana
            onButtonPressed: {
                target_button = button;
                state = "pressed"
            }
        
            onButtonReleased: {
                target_button = button;
                state = "released"
            }
        
            onButtonRollOver: {
                target_button = button;
                event_x = originX;
                event_y = originY;
                state = "rollover"
            }
        }
        
        Connections {
            target: Katana
            onRebindViewSize: {
                mainView.width = Katana.viewWidth
                mainView.height = Katana.viewHeight
        
            }
        }
        
        states: [
            State {
                name: "pressed"
                PropertyChanges { target: target_button; opacity: 0.2; }
            },
            State {
                name: "released"
                PropertyChanges { target: target_button; opacity: 1.0; }
            },
            State {
                name: "rollover"
                PropertyChanges { target: target_button; opacity: 0.4; }
            }
        
        ]
        
        transitions: [
            Transition {
                 to: "pressed"; reversible: false
                 ParallelAnimation {
                     NumberAnimation { properties: "opacity"; duration: 300; easing.type: Easing.InOutQuad }
                 }
             },
            Transition {
                 to: "released"; reversible: false
                 ParallelAnimation {
                     NumberAnimation { properties: "opacity"; duration: 300; easing.type: Easing.InOutQuad }
                 }
             },
            Transition {
                 to: "rollover"; reversible: true
                 ParallelAnimation {
                     NumberAnimation { properties: "opacity"; duration: 100; easing.type: Easing.InOutQuad }
                 }
             }
        
        ]
        

        }@

        As posted, this current method works, by declaring target_button as a property variant, I am able to access it through-out the qml file, however, when altering the yRotation of the button, press/release animations are only correct on the first button spawned, the other buttons' animation for release is only updated on the press event of another button in the scene.

        1 Reply Last reply
        0
        • D Offline
          D Offline
          Decessus
          wrote on last edited by
          #4

          window.cpp
          @#include "window.h"
          #include "ui_window.h"

          Window::Window(QWidget *parent) :
          QWidget(parent),
          ui(new Ui::Window)
          {
          this->setupQmlTypes();
          ui->setupUi(this);
          scene = new QGraphicsScene(this);
          QGraphicsWidget *widget = new QGraphicsWidget();
          QGraphicsGridLayout *grid = new QGraphicsGridLayout(widget);
          QGraphicsView *view = new QGraphicsView(scene);
          m_button = new AnimatedButton;
          scene->addItem(widget);

          ui->verticalLayout->addWidget(view);
          
          for(qint8 i = 0; i < 5; i++) {
              qDebug() << "here";
              AnimatedButton* n_button = new AnimatedButton();
              scene->addItem(n_button);
              n_button->setGeometry((100 * i) + (5 * i),0,100,100);
              n_button->setZValue(100);
              connect(n_button,SIGNAL(pressed(AnimatedButton*)),this,SLOT(buttonPressing(AnimatedButton*)));
              connect(n_button,SIGNAL(released(AnimatedButton*)),this,SLOT(buttonReleasing(AnimatedButton*)));
          }
          
          engine.addPluginPath(QApplication::applicationDirPath());
          //QDeclarativeContext
          
          // encapsulates a QML component definition
          QDeclarativeComponent component(&engine,QUrl(QString("qrc:/scripts/qml/Katana/main.qml")));
          
          // creates the graphics item for QML at the engine's root context
          QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create());
          
          if(item) {
              scene->addItem(item);
          
          }
          
          loadedPlugins.append(&component);
          
          view->setRenderHint(QPainter::Antialiasing,true);
          
          qDebug() << component.errors();
          
          this->setLayout(ui->verticalLayout);
          
          Q_EMIT finishedLoading();
          m_button->setVisible(true);
          //m_button->raise();
          

          }

          Window::~Window()
          {
          delete ui;
          }

          void Window::setupQmlTypes() {
          qmlRegisterType<AnimatedButton>();
          engine.rootContext()->setContextProperty(QString("Katana"),this);
          }

          void Window::buttonClicking(AnimatedButton* button) {
          Q_EMIT buttonClicked(button);
          }

          void Window::buttonPressing(AnimatedButton *button) {
          Q_EMIT buttonPressed(button);
          }

          void Window::buttonReleasing(AnimatedButton* button) {
          Q_EMIT buttonReleased(button);
          }

          void Window::buttonHoverIn(AnimatedButton* button,int originX,int originY) {
          Q_EMIT buttonRollOver(button,originX,originY);
          }

          void Window::buttonHoverOut(AnimatedButton* button,int originX,int originY) {
          Q_EMIT buttonRollOut(button,originX,originY);
          }

          void Window::buttonHoverMove(AnimatedButton *button, int originX, int originY) {
          Q_EMIT buttonRolling(button,originX,originY);
          }

          int Window::viewHeight() const {
          return height() - 10;
          }

          int Window::viewWidth() const {
          return width() - 10;
          }

          void Window::resizeEvent(QResizeEvent *event) {
          emit rebindViewSize();
          }@

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved