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. Calling a C++ function inside a property subclass from QML
Forum Updated to NodeBB v4.3 + New Features

Calling a C++ function inside a property subclass from QML

Scheduled Pinned Locked Moved QML and Qt Quick
13 Posts 8 Posters 20.7k 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
    DenisKormalev
    wrote on last edited by
    #4

    thp, we have similar way as author has to call c++ from qml. In our design we have on class that has pointers to all objects that are needed for qml interaction and doesn't have any methods other than simple getters for this objects. This gives us ability to pass only one object as contextproperty to qml for all interaction between qml and c++.

    1 Reply Last reply
    0
    • L Offline
      L Offline
      luizpaulo
      wrote on last edited by
      #5

      Well it's not working...
      A more complete example follows:

      class1.h:

      @
      class Class1 : public QObject
      {
      Q_OBJECT
      Q_PROPERTY(SubClass1 subclass1 READ subclass1)

      private:
         SubClass1 _subclass1;
      
      public slots:
         SubClass1 subclass1() {return _subclass1;}
      

      };
      @

      subclass1.h:

      @
      class SubClass1 : public QObject
      {
      Q_OBJECT

      public:
          SubClass1(QObject *parent = 0);
          SubClass1(const SubClass1 &);
          SubClass1 &operator=(const SubClass1 &);
      
      public slots:
          void method() {qDebug("method");}
      

      };
      @

      main.cpp:
      @
      ...
      qRegisterMetaType<SubClass1>("SubClass1");
      qmlRegisterInterface<Class1>("Class1");
      qmlRegisterInterface<SubClass1>("SubClass1");

      context->setContextProperty("Class1", new Class1);;
      

      ...
      @

      qml:
      @
      Button {
      id: btn
      image: "img.svg"
      onButtonClicked: { class1.subclass1().method(); }
      }
      @

      Doesn't work. I've tried qmlRegisterUncreatableType and qmlRegisterType as well it didn't work. All I get is this:
      TypeError: Result of expression 'class1.subclass1' [QVariant(SubClass1)] is not a function.

      If I remove the MetaType stuff I get this:
      TypeError: Result of expression 'class1.subclass1' [undefined] is not a function.

      Any other ideas?

      1 Reply Last reply
      0
      • G Offline
        G Offline
        giesbert
        wrote on last edited by
        #6

        Is it case sensitive? I never tried this up to now, but in C++ you have to take care of case... How is this in Qml code? Ifit is case sensitive, it should be:

        @
        Button {
        id: btn
        image: "img.svg"
        onButtonClicked: { Class1.subclass1().method(); }
        }
        @

        Nokia Certified Qt Specialist.
        Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

        1 Reply Last reply
        0
        • C Offline
          C Offline
          coderbob
          wrote on last edited by
          #7

          I believe this could be a bug and related to http://developer.qt.nokia.com/forums/viewthread/1764/
          filed as http://bugreports.qt.nokia.com/browse/QTBUG-15712 (Voting on it might get it fixed faster)

          Change your return type to a QObject and use qobject_cast<T>() in your c++ code if you need to access it there also.

          1 Reply Last reply
          0
          • D Offline
            D Offline
            DenisKormalev
            wrote on last edited by
            #8

            coderbob, yes qobject_cast will help author in using objects from qml, but if all methods will return qobjects or there will be duplicated methods (one return qobject, one normal type) then it can lead to design problems.

            1 Reply Last reply
            0
            • C Offline
              C Offline
              coderbob
              wrote on last edited by
              #9

              Denis, I think you misunderstood the solution. There are no duplicate functions. You have to use QObject to be able to access correctly in QML. The side effect of this is that you lose your defined types in the c++ code. To solve this you have to qcast them when accessed there. Only one function is needed but you will have to cast.

              This is not how I want to write my code but it is the best solution I could come up with to work around this bug until it is fixed.

              1 Reply Last reply
              0
              • N Offline
                N Offline
                Nayar
                wrote on last edited by
                #10

                I'm still having this problem on my friend's windows machine.

                Windows:-
                It calls the function as the program loads. But when called again, the program crashes

                Linux:-
                It works for some times. Then it crashes.

                Else, it would say it is not a function. I guess QML is loosing some infomation. Maybe garbage collector is destroying the link to the function after some time.

                1 Reply Last reply
                0
                • X Offline
                  X Offline
                  Xander84
                  wrote on last edited by
                  #11

                  if your app is crashing it's more likely that you have an invalid pointer in the c++ code I would say, but hard to tell without seeing any code or something.
                  also just start the app in debug mode then you should see the stacktrace when the app crashes and what function it crashes etc.

                  1 Reply Last reply
                  0
                  • N Offline
                    N Offline
                    Nayar
                    wrote on last edited by
                    #12

                    Here's the QML
                    @ListView {
                    id: listViewRulesStrength
                    MouseArea {
                    anchors.fill: parent
                    onClicked: {
                    listViewRulesStrength.model = m.fce().rulesStrength();
                    }
                    }
                    model: m.fce().rulesStrength()
                    delegate: Item {
                    Row {
                    id: row2
                    Text {
                    text: modelData.rule
                    height: paintedHeight
                    }
                    }
                    }@

                    The C++ code for m.fce() in class Mixture

                    @FuzzyCompostEngine * Mixture::fce()
                    {
                    return m_engines;
                    }@

                    The C++ code for rulesStrenght in FuzzyCompostEngine

                    @
                    QList<QObject *> FuzzyCompostEngine::rulesStrength()
                    {
                    qDebug() << "Starting rule strength";
                    for(int i = 0;i<m_rulesStrength.size();i++){
                    RuleStrength *tmp = (RuleStrength *) m_rulesStrength.first();
                    m_rulesStrength.removeFirst();
                    delete tmp;
                    }

                    qDebug() << "rule strength";
                    fl::Engine *engine;
                    for(int i = 0;i < engines.size();i++){
                        engine = engines.at(i);
                        fl::RuleBlock *ruleBlock = engine->getRuleBlock(0);
                        if(ruleBlock != NULL)
                        {
                            for(int j = 0; j < ruleBlock->numberOfRules() ; j++){
                                fl::Rule *rule =  engine->getRuleBlock(0)->getRule(j);
                                scalar degree = rule->firingStrength(ruleBlock->getTnorm(),ruleBlock->getSnorm());
                                //qDebug() << "Degree" << degree;
                                if(std::isnan(degree) == 0 && degree > 0.01){
                                    //rules << QString::fromStdString(rule->getUnparsedRule()) + " : " + QString::number(degree,'f',2);
                                    m_rulesStrength.append(new RuleStrength(QString::fromStdString(rule->getUnparsedRule()),degree));
                                }
                            }
                        }
                    }
                    std::sort(m_rulesStrength.begin(),m_rulesStrength.end(),RuleStrength::isGreater);
                    qDebug() << "Ending";
                    return m_rulesStrength;
                    

                    }
                    @

                    When it crashes, it doesn't even start the C++ function rulesStrength. because the qDebug doesn't get displayed

                    Sometimes when clicking a lot, i get the error

                    bq. qrc:/qml/mainwindow.qml:274: TypeError: Cannot call method 'rulesStrength' of null

                    However, the problem gets fixed when i call the function from mixture directly.

                    new QML model in listwidget
                    @
                    MouseArea {
                    anchors.fill: parent
                    onClicked: {
                    listViewRulesStrength.model = m.rulesStrength();
                    }
                    }
                    model: m.rulesStrength()
                    @

                    I added a function in Mixture like this to call fce() from inside

                    @QList<QObject *> Mixture::rulesStrength()
                    {
                    return fce()->rulesStrength();
                    }@

                    Now it runs fine on windows and doesn't crash or lose the object in QML on Linux

                    Reminder: The initial code does run fine as it should have for some time only on Linux.

                    1 Reply Last reply
                    0
                    • T Offline
                      T Offline
                      Torgeir
                      wrote on last edited by
                      #13

                      When you use a construct like
                      @m.fce().rulesStrength()@

                      you need to be careful about object ownership of the object returned by fce(). If this object has no explicit parent set or doesn't have explicit CppOwnership set, then QML will assume ownership and will destruct it when it is no longer referenced.

                      You can check if it gets destructed by setting a breakpoint in the desctructor for example.

                      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