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. Trying to implement an ObjectPool design pattern with a TabBarLayout
Forum Updated to NodeBB v4.3 + New Features

Trying to implement an ObjectPool design pattern with a TabBarLayout

Scheduled Pinned Locked Moved QML and Qt Quick
10 Posts 3 Posters 5.0k 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.
  • P Offline
    P Offline
    pavneetarora
    wrote on last edited by
    #1

    I have (one part) of my calculator object working fine as a single instance. My next step is to use a TabBarLayout to quickly compare different sets of equation values; 5 in my case.

    My approach is to create an object pool class with an array of 5 pointers to previously instantiated calcXY objects. As the user swipes left-to-right or selects a TabButton, I would like the displayed QML to get its values from the appropriate calcXY object, the currXYObject being set by a call to the calcXYPool object. Since the public slots are in the individual calcXY objects, both the pool and calculator class are defined as subclasses of QObject:

    @
    class CalcXY : public QObject
    {
    Q_OBJECT
    ...
    @

    I first tried to use the late instantiation "singleton":http://stackoverflow.com/questions/1008019/c-singleton-design-pattern#1008289 pattern. But that give me a slew of compile errors which I wasn't able to resolve. So I reverted back to the simpler template of a Q_OBJECT class, since the class instance is controlled by the following in any case. I'll leave the singleton implementation until later:

    @
    viewer.rootContext()->setContextProperty("calcXYPoolObject", &calcXYPool);
    @

    So then the TabButton event call would be something like this:

    @
    TabButton { tab: aModel; text: "A"; onClicked: calcXYPoolObject.setCurrCalcXY(0) }
    TabButton { tab: bModel; text: "B"; onClicked: calcXYPoolObject.setCurrCalcXY(1) }
    ...
    @

    The CalcXYPool class is quite simple:

    @
    CalcXYPool::CalcXYPool(QObject *parent) :
    QObject(parent)
    {
    int i;

    // Set up instances of CalcXY.
    for (i=0; i<NUMCALCS; i++) {
        calcXYs[i] = new CalcXY((QObject *)0);  // I don't know if this is correct.  I was trying to cast the parent as per the declaration is the .h file
    }
    

    }

    void CalcXYPool::setCurrCalcXY(int calcIndex) {
    currCalcXY = calcXYs[calcIndex];
    }

    CalcXY CalcXYPool::getCurrCalcXY(void) {
    return currCalcXY;
    }
    @

    However, I continue to get errors that I am not able to understand:

    @
    error: no match for 'operator=' in '((CalcXYPool*)this)->CalcXYPool::calcXYs[i] = (operator new(36u), (<statement>, ((CalcXYPool*)<anonymous>)))'
    @

    and the following:

    @
    error: 'QObject::QObject(const QObject&)' is private
    error: within this context
    In member function 'CalcXY CalcXYPool::getCurrCalcXY()':
    @

    Any help that could be provided would be much appreciated. Or if there is a better way of doing what I want to do, I would be grateful for some pointers.

    advTHANKSance.

    1 Reply Last reply
    0
    • D Offline
      D Offline
      dridk
      wrote on last edited by
      #2

      Why are you not using QList<CalcXY*> instead ?
      Do the calcXY constructor like this :

      @class CalcXY : public QObject
      {
      Q_OBJECT
      public:
      CalcXY(QObject * parent = 0);

      }@

      And then :
      @
      for (i=0; i<NUMCALCS; i++) {
      calcXYList.append(new CalcXY);
      }
      @

      Nothing in Biology Makes Sense Except in the Light of Evolution

      1 Reply Last reply
      0
      • P Offline
        P Offline
        pavneetarora
        wrote on last edited by
        #3

        I attempted to do what you suggested, although initially I had:

        @
        public:
        explicit CalcXY(QObject *parent = 0);
        @

        When I use void in the constructor, I get:

        @
        error: return type specification for constructor invalid
        @

        That aside, when I use the QList approach, I get the following error:

        @
        error: no matching function for call to 'QList<CalcXY>::append(CalcXY*)'
        @

        in response to the line:

        @
        calcXYList.append(new CalcXY);
        @

        My CalcXYPool has the following:

        @
        class ScreenRatioCalcPool : public QObject
        {
        Q_OBJECT

        private:
            QList<CalcXY> calcXYList;
            CalcXY   currCalcXY;
        

        @

        I must be missing something obvious?

        1 Reply Last reply
        0
        • M Offline
          M Offline
          mlong
          wrote on last edited by
          #4

          The error message
          @
          error: no matching function for call to 'QList<CalcXY>::append(CalcXY*)'
          @
          tells all.

          Your QList is a list of CalcXY objects. Trying to append "new CalcXY()" is trying to append a pointer to CalcXY (thus the CalcXY*).

          If you look at dridk's example, you'll see that he has a QList<CalcXY*> which is a list of CalcXY pointers, which is what you need if you want to append an object created via new.

          There's a big difference between an object and a pointer to an object. :-)

          Software Engineer
          My views and opinions do not necessarily reflect those of anyone -- living or dead, real or fictional -- in this universe or any other similar multiverse node. Void where prohibited. Your mileage may vary. Caveat emptor.

          1 Reply Last reply
          0
          • D Offline
            D Offline
            dridk
            wrote on last edited by
            #5

            And there is no "void" in the constructor. this is a mistake from me..

            Nothing in Biology Makes Sense Except in the Light of Evolution

            1 Reply Last reply
            0
            • P Offline
              P Offline
              pavneetarora
              wrote on last edited by
              #6

              [quote author="mlong" date="1332871529"]

              If you look at dridk's example, you'll see that he has a QList<CalcXY*> which is a list of CalcXY pointers, which is what you need if you want to append an object created via new.

              [/quote]

              Perfect. I missed that. Thanks.

              1 Reply Last reply
              0
              • M Offline
                M Offline
                mlong
                wrote on last edited by
                #7

                And, I'm guessing that currCalcXY should be a CalcXY* too instead of a CalcXY, or perhaps you should just keep track of an integer which is an index into your QList of CalcXY pointers.

                Then you could simplify things with an accessor method
                @
                CalcXY* CalcXYPool::current()
                {
                if (currCalcXY >= 0 && currCalcXY < calcXYList.count()) {
                return calcXYList.at(currCalcXY);
                } else {
                qWarning("Current CalcXY item is invalid! Returning 0.");
                return 0;
                }
                }
                @
                (Brain to terminal; ymmv)

                Software Engineer
                My views and opinions do not necessarily reflect those of anyone -- living or dead, real or fictional -- in this universe or any other similar multiverse node. Void where prohibited. Your mileage may vary. Caveat emptor.

                1 Reply Last reply
                0
                • P Offline
                  P Offline
                  pavneetarora
                  wrote on last edited by
                  #8

                  That is much cleaner! Ultimately, I need to get the QML to point to the currCalcXY.

                  So something like this I am guessing?

                  @
                  // Ignore the exitingField toggle. I'll incorporate dridk's template shortly.
                  onActiveFocusChanged: {calcXYObject.toggleExitingField();
                  calcXYPoolObject.current().setX(x.text)}
                  @

                  to set the x-value of the current calculator.

                  Still in the process of mapping my decades old experience in NeXTSTEP programming to Qt (and C++) ;).

                  Cheers.

                  1 Reply Last reply
                  0
                  • P Offline
                    P Offline
                    pavneetarora
                    wrote on last edited by
                    #9

                    As expected, I am still short on some QML subtleties ;).

                    Using the above example I get the following error:

                    @
                    Result of expression 'calcXYPoolObject.getCurrCalc().setX' [undefined] is not a function.
                    @

                    So I am guessing that I need to cast 'calcXYPoolObject.getCurrCalc()' to (CalcXY *) because QML doesn't know the interface to the CalcXY class, but how to do that in QML. Any suggestions? I hope that I don't need to promote the entire interface of CalcXY into CalcXYPool.

                    BTW, I have confirmed using qDebug() that both the calcXYList is populated, and that in the snippet provided by mlong that we are returning a valid calcXY from the calcXYList.

                    Thanks.

                    1 Reply Last reply
                    0
                    • P Offline
                      P Offline
                      pavneetarora
                      wrote on last edited by
                      #10

                      So, I have tried another approach, which I thought might work, but still no success.

                      Following mlong's suggestion, I only keep track of the integer value of the currCalcXY. But since I don't know how to cast back to the calcXYObject in QML, I am trying to set/reset the calcXYObject inside C++ (but not in main). That way the QML can remain simple.

                      @
                      // Store the pointer to the viewer so that CalcXYPool can setContextProperty
                      void CalcXYPool::setAppViewer(QmlApplicationViewer *viewer) {
                      appViewer=viewer;
                      }
                      @

                      @
                      void CalcXYPool::setCurrCalcXY(int calcIndex) {
                      currCalcXY = calcIndex;
                      (*appViewer).rootContext()->setContextProperty("calcXYObject", calcXYList.at(currCalcXY));
                      }
                      @

                      In main, I call:

                      @
                      QmlApplicationViewer viewer;

                      calcXYPool.setAppViewer(&viewer);
                      

                      @

                      and in the QML, I can just go back to:

                      @
                      // Now we should be able to directly reference calcXYObject rather
                      // than having to cast calcXYObjectPool.current()
                      onActiveFocusChanged: {calcXYObject.toggleExitingField();
                      calcXYObject.setX(x.text)}
                      @

                      I thought that it was a good idea. Unfortunately, it didn't work :(.

                      @
                      calcxy.qml:52: ReferenceError: Can't find variable: calcXYObject
                      @

                      Any thoughts or suggestions?

                      Thanks.

                      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