Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Learning
  3. Qt in Education
  4. Need Help with QList !
QtWS25 Last Chance

Need Help with QList !

Scheduled Pinned Locked Moved Qt in Education
qlistpointersobjectseraseqlist
7 Posts 3 Posters 3.4k Views
  • 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.
  • A Offline
    A Offline
    Afterwork
    wrote on 17 Apr 2015, 17:36 last edited by
    #1

    Hello everyone ! I need help ! I store the objects for painting in QList .
    What is better to store painters or the objects ?
    And how erase the QList ? ( depend on objects of QList is pointers or objects )

    QList <Object> Menu::objects()
    {
        QList <Object> objects;
        Object object(QRect(100,100,600,189),":/images/logo.png");
        objects.push_back(object);
    
        return objects;
    }
    
    void GameWidget::paintEvent(QPaintEvent *event)
    {
        QPainter painter(this);
     foreach(const Object& obj,Game::Instance().current->objects())
        {
            painter.drawPixmap(obj.size,QPixmap(obj.pixmap));
        }
    
        timer->start(10);
    
    }
    
    void Menu::clearList()
    {
        // What to write ?
    }
    
    1 Reply Last reply
    0
    • M Offline
      M Offline
      mcosta
      wrote on 17 Apr 2015, 17:42 last edited by
      #2

      Hi and Welcome to devnet,

      if Object is a subclass of QObject you cannot store objects inside a list but you must use pointers; this because QObject is not copyable.

      Once your problem is solved don't forget to:

      • Mark the thread as SOLVED using the Topic Tool menu
      • Vote up the answer(s) that helped you to solve the issue

      You can embed images using (http://imgur.com/) or (http://postimage.org/)

      1 Reply Last reply
      0
      • C Online
        C Online
        Chris Kawa
        Lifetime Qt Champion
        wrote on 17 Apr 2015, 19:46 last edited by Chris Kawa
        #3

        Looking at your code I assume Object is not a QObject derived. In that case it depends on the size of the object and the cost of copy.
        As for clearing the list - currently you're passing it by value so if the list contains objects (not pointers) then the objects will be destroyed automatically upon list destruction. If you'll be keeping pointers then you can delete all objects at once using qDeleteAll and then clear() to empty the list of invalidated pointers.

        Some performance tips:

        • If you store the objects somewhere already and creating that list to point to only some of them then a list of pointers is a natural choice (to avoid copies).
        • In other case it will be more cache friendly to keep objects instead of pointers so unless the Object class is big and the list will hold thousands of them I would vote for keeping objects.
        • Consider switching to QVector and calling reserve before filling it. You will avoid many reallocations and get a much better cache locality when iterating over it.
        • If you're on a c++11 compiler and decide to store objects instead of pointers consider switching to std::vector and using emplace_back instead of push_back. This will save you from unnecessary copy when placing the objects in a container (the reserve tip also applies here).
        • Don't do this: painter.drawPixmap(obj.size,QPixmap(obj.pixmap));. This creates a temporary copy of the pixmap which you already have. Instead do this: painter.drawPixmap(obj.size, obj.pixmap);

        Bonus remark: paintEvent is a weird place to start a timer. Also, if the timer has anything to do with painting, then interval of 10ms is way too small for most consumer grade displays (which usually ticks at 60Hz --> 16.66...ms per frame).

        A 1 Reply Last reply 18 Apr 2015, 06:54
        0
        • C Chris Kawa
          17 Apr 2015, 19:46

          Looking at your code I assume Object is not a QObject derived. In that case it depends on the size of the object and the cost of copy.
          As for clearing the list - currently you're passing it by value so if the list contains objects (not pointers) then the objects will be destroyed automatically upon list destruction. If you'll be keeping pointers then you can delete all objects at once using qDeleteAll and then clear() to empty the list of invalidated pointers.

          Some performance tips:

          • If you store the objects somewhere already and creating that list to point to only some of them then a list of pointers is a natural choice (to avoid copies).
          • In other case it will be more cache friendly to keep objects instead of pointers so unless the Object class is big and the list will hold thousands of them I would vote for keeping objects.
          • Consider switching to QVector and calling reserve before filling it. You will avoid many reallocations and get a much better cache locality when iterating over it.
          • If you're on a c++11 compiler and decide to store objects instead of pointers consider switching to std::vector and using emplace_back instead of push_back. This will save you from unnecessary copy when placing the objects in a container (the reserve tip also applies here).
          • Don't do this: painter.drawPixmap(obj.size,QPixmap(obj.pixmap));. This creates a temporary copy of the pixmap which you already have. Instead do this: painter.drawPixmap(obj.size, obj.pixmap);

          Bonus remark: paintEvent is a weird place to start a timer. Also, if the timer has anything to do with painting, then interval of 10ms is way too small for most consumer grade displays (which usually ticks at 60Hz --> 16.66...ms per frame).

          A Offline
          A Offline
          Afterwork
          wrote on 18 Apr 2015, 06:54 last edited by
          #4

          @Chris-Kawa Ohhh! Thanks a lot !!!! You give a most nedeed information !
          I use timer to update GameWidget ( inherited from QWidget) to paint objects.

          GameWidget::GameWidget(QWidget *parent)
              : QWidget(parent)
          {
              resize(800,600);
              timer = new QTimer(this);
              timer->stop();
              connect(timer,SIGNAL(timeout()),this,SLOT(update()));
          }
          

          And as for Object:

          class Object
          {
          public:
              QRect size;
              QPixmap pixmap;
          
              Object(QRect rect, QString load)
              {
                  size = rect;
                  pixmap.load(load);
              }
          
              ~Object(){};
          };
          

          For such object is better store in vector of objects ?
          And i have a leak of memeory.I think it's caused by updating every milisecond the paintEvent wich call the QList <Object*> objects() method that creates the objects,and don't delete them.Am I right ?

          1 Reply Last reply
          0
          • C Online
            C Online
            Chris Kawa
            Lifetime Qt Champion
            wrote on 18 Apr 2015, 08:07 last edited by
            #5

            Well yeah. If you allocate memory dynamically and don't delete it it's gonna leak.

            As for objects or pointers - do you store them somewhere or do you recreate them every frame?

            As for the timer - by calling start in the paint event you are restarting it every time. That's a weird thing to do. If I may suggest a different approach: Don't create you own timer. Start the built-in timer of the GameWidget. Set it to desired interval (e.g. 30FPS = 1000ms/30= 33.333ms, 60FPS = 1000ms/60=16.666ms). Then override the timerEvent and call update and repaint there.

            A 1 Reply Last reply 18 Apr 2015, 14:43
            0
            • C Chris Kawa
              18 Apr 2015, 08:07

              Well yeah. If you allocate memory dynamically and don't delete it it's gonna leak.

              As for objects or pointers - do you store them somewhere or do you recreate them every frame?

              As for the timer - by calling start in the paint event you are restarting it every time. That's a weird thing to do. If I may suggest a different approach: Don't create you own timer. Start the built-in timer of the GameWidget. Set it to desired interval (e.g. 30FPS = 1000ms/30= 33.333ms, 60FPS = 1000ms/60=16.666ms). Then override the timerEvent and call update and repaint there.

              A Offline
              A Offline
              Afterwork
              wrote on 18 Apr 2015, 14:43 last edited by
              #6

              @Chris-Kawa said:

              As for objects or pointers - do you store them somewhere or do you recreate them every frame?

              I recreate them every time. Are there better way ?
              And how i can connect the slot of differents objects to built-in timer of QWidget ?

              1 Reply Last reply
              0
              • C Online
                C Online
                Chris Kawa
                Lifetime Qt Champion
                wrote on 18 Apr 2015, 16:04 last edited by Chris Kawa 3 Sept 2017, 07:37
                #7

                @Afterwork said:

                I recreate them every time. Are there better way ?

                If they change then there's no way around it but if they're the same every frame then it's a waste of time. Generate the list once, store it as a class member and just expose them by reference e.g.

                //split that to .h and .cpp of course
                class GameWidget : public QWidget {
                   Q_OBJECT
                public:
                   GameWidget(QWidget* parent = nullptr) : QWidget(parent) {
                      generateMyListOfObjects();
                   }
                   const QVector<Object>& objects() const { return objects_; }
                private:
                    void generateMyListOfObjects() {
                         //fill the objects vector here
                    }
                   QVector<Object> objects_;
                 };
                

                And how i can connect the slot of differents objects to built-in timer of QWidget ?

                You don't. As I said - reimplement the timerEvent method. It will be called every time the timer times out. You can call some methods directly in it or emit a custom signal if you'd like.

                1 Reply Last reply
                0

                1/7

                17 Apr 2015, 17:36

                • Login

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