September 13, 2011

SnowmanX SnowmanX
Lab Rat
11 posts

signals with custom objects in QML

 

Hi everyone,

I’m playing with custom objects and signals in QML and I have a problem with making the signal parameter to be correctly visible by the script handling the signal. I’m extending the BirthdayParty/Persons example from here http://doc.qt.nokia.com/4.7-snapshot/declarative-cppextensions-referenceexamples-properties.html and I have all classes in my custom namespace (issue being solved using this topic: http://developer.qt.nokia.com/forums/viewthread/9509/ ) Anyway I added PersonEvent class, and somethingHappened(PersonEvent *event) signal to Person class. Later I register PersonEvent class using qmlRegisterType<XX::PersonEvent>(); The class declaration is something like this:

  1. class PersonEvent;
  2.  
  3. class Person : public SuperPerson
  4. {
  5.     Q_OBJECT    
  6.     Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize)
  7. public:
  8.     virtual ~Person();
  9.     int shoeSize() const;
  10.     void setShoeSize(int);
  11.     void triggerEvent(PersonEvent *event);
  12. protected:
  13.     Person();
  14. Q_SIGNALS:
  15.     void somethingHappened(XX::PersonEvent *event);
  16. private:
  17.     int m_shoeSize;
  18.     Q_DISABLE_COPY(Person)
  19. };
  20.  
  21.  
  22.  
  23. class PersonEvent: public QObject/*, QEvent*/ {
  24.     Q_OBJECT
  25.     Q_PROPERTY(bool lifeThreatening READ isLifeThreatening)
  26.     Q_PROPERTY(XX::Person* causingPerson READ causingPerson)
  27. public:
  28.     PersonEvent(Person *causingPerson, bool isLifeThreatening);
  29.     virtual ~PersonEvent();
  30.     bool isLifeThreatening() const;
  31.     XX::Person * causingPerson() const;
  32. private:
  33.      bool m_isLifeThreatening;
  34.      Person *m_causingPerson;
  35.      Q_DISABLE_COPY(PersonEvent)
  36. };

Now when I call triggerEvent(PersonEvent*) this function just simply emits the signal (emit somethignHappened(event))). In C++ I can easily connect to this signal and I get the correct event. In QML, however, I’m trying to process the event using this snippet:

  1. import People 1.0
  2.  
  3. BirthdayParty {
  4.     host: Girl {
  5.         name: "Jean Jones"
  6.         onSomethingHappened: {
  7.             console.log(" something happened !!! " +somethingHappened);
  8.             console.log(" is it life threating? " + somethingHappened.isLifeThreatening);
  9.         }
  10.     }
  11.     guests: [
  12.         Boy { name: "Leo Hodges" },
  13.         Boy { name: "Jack Smith" },
  14.         Girl { name: "Anne Brown" }
  15.     ]
  16. }

The signal gets fired correctly, the problem I have is with accessing the properties of the PersonEvent object. When running the qml code above (and firing the signal by calling host->triggerEvent(PersonEvent*)) the output is like this:

something happened !!! [object Object] is it life threating? undefined

So the signal is emitted correctly, the qml handler is called correctly, but the actual signal parameter does not seem to be visible from QML. Is there anything I need to do specifically in the event object to make sure it is visible to the script?

5 replies

September 13, 2011

mbrasser mbrasser
Lab Rat
452 posts

Hi,

Note that for the following line:

  1. console.log(" is it life threating? " + somethingHappened.isLifeThreatening);

You’ll need to use somethingHappened.lifeThreatening (i.e. drop the is, which is not part of the property name)

Regards,
Michael

September 13, 2011

SnowmanX SnowmanX
Lab Rat
11 posts

Oops, my fault. Fixed it, but the code still fails. The same message and I believe it is because the object is not recognized by QML (see the first line, that the output says [object Object]).

September 15, 2011

SnowmanX SnowmanX
Lab Rat
11 posts

Anyone?>

September 15, 2011

sigrid sigrid
Lab Rat
138 posts

Make sure that the name of the signal parameter and the parameters in the qml code are the same. When doing so it works for me in the example below. If the name differs, I get the same problem you are having. Does the example below work correctly for you?

  1. #include <QtGui>
  2. #include <QtDeclarative>
  3.  
  4. namespace YY {
  5.  class PersonEvent: public QObject {
  6.   Q_OBJECT
  7.    Q_PROPERTY(bool lifeThreatening READ isLifeThreatening)
  8.  public:
  9.   PersonEvent()
  10.   {}
  11.   bool isLifeThreatening() const
  12.   {
  13.    return true;
  14.   }
  15.  };
  16. }
  17.  
  18. using namespace YY;
  19. QML_DECLARE_TYPE(PersonEvent)
  20.  class Person : public QObject
  21.  {
  22.   Q_OBJECT  
  23.  public:
  24.  
  25.   Q_INVOKABLE  void triggerEvent(PersonEvent * event)
  26.   {
  27.    emit somethingHappened(event);
  28.   }
  29.   Person()
  30.   {
  31.    qDebug() << "timer triggers";
  32.    startTimer(1000);
  33.   }
  34.   void timerEvent(QTimerEvent *e)
  35.   {
  36.    PersonEvent *myEvent = new PersonEvent();
  37.    triggerEvent(myEvent);
  38.   }
  39. signals:
  40.   void somethingHappened(PersonEvent *event);
  41.  };
  42. QML_DECLARE_TYPE(Person)
  43.  
  44. #include "main.moc"
  45. int main(int argc, char** argv)
  46. {
  47.  QApplication app(argc, argv);
  48.  qmlRegisterType<Person>("People", 1, 0, "Person");
  49.  qmlRegisterType<PersonEvent>("People", 1, 0, "PersonEvent");
  50.  Person myObj;
  51.  PersonEvent personEvent;
  52.  QDeclarativeView view;
  53.  view.rootContext()->setContextProperty("rootItem", (Person *)&myObj);
  54.  view.rootContext()->setContextProperty("eventItem", (PersonEvent *)&personEvent);
  55.  
  56.  view.setSource(QUrl::fromLocalFile("main.qml"));
  57.  view.resize(200,100);
  58.  view.show();
  59.  return app.exec();
  60. }

  1. main.qml
  2. import People 1.0
  3. import QtQuick 1.0
  4. Text {
  5.  
  6. Person {
  7.     onSomethingHappened: {
  8.     console.log(" something happened !!! " +event);
  9.  console.log(" is it life threating? " + event.lifeThreatening);
  10.     }
  11. }
  12. }

September 15, 2011

SnowmanX SnowmanX
Lab Rat
11 posts

Thanks!!! This was it. The problem I was seeing I guess was I used the same name of the javascript variable as the signal, but it contained the signal itself as some sort of object (and thus not failing), but it was not the actual event parameter. When I changed it to “event”, everything works. Thanks again!

 
  ‹‹ How to make ListView content to follow anchor changes      Context object being available to JS ››

You must log in to post a reply. Not a member yet? Register here!