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. How to load a piece of an image to QML-form on timer signal
Forum Updated to NodeBB v4.3 + New Features

How to load a piece of an image to QML-form on timer signal

Scheduled Pinned Locked Moved QML and Qt Quick
11 Posts 4 Posters 4.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.
  • G Offline
    G Offline
    gggfggg
    wrote on last edited by
    #1

    Hello everybody,

    This is my first experience in QML. My task is to load a random piece (square) of a big image to QML-form on timer signal. The least of application is wriiten in C++, so I decided to realize timer and copying the part of the image in C++-model and display them through QQuickPaintedItem, redefined paint() and calling update() in the slot of the item.

    This is how I redefined paint ():
    @SomeItem::paint( QPainter *painter )
    {
    painter -> eraseRect( contentsBoundingRect());
    painter -> drawImage( QPoint(0,0), image );
    }@

    This is QML-file with registered item:
    @import QtQuick 2.0
    import SomeItem 1.0

    Rectangle {
    width: 500
    height: 500
    SomeItem {
    width: 100
    height: 100
    }
    }@

    I see no result. To make check easier, I temporarily put in paint() this code:
    @SomeItem::paint( QPainter *painter )
    {
    painter -> eraseRect( contentsBoundingRect());
    painter -> fillRect( contentsBoundingRect(), Color );
    }@

    Color is declared as Q_PROPERTY and I change it on timer signal, then slot emits Color_Changed() and calls update(). This time I see the result, but the color doesn't change. QML-form shows only the first color with which I initialized Color in item constructor.
    I have a few questions about it:
    What am I doing wrong?
    How to declare Q_PROPERTY for QImage correctly in this case?
    In standard widgets I use the second thread for random coordinates calculation and copying of the part of bigger QImage to the smaller to avoid the stop of event handling by interface. Is there any use in doing it in QML?

    Thank you.

    1 Reply Last reply
    0
    • p3c0P Offline
      p3c0P Offline
      p3c0
      Moderators
      wrote on last edited by
      #2

      Hi,

      AFAIK, you can't use QImage as QML element using Q_PROPERTY.
      Use "qquickimageprovider":http://qt-project.org/doc/qt-5.0/qtquick/qquickimageprovider.html.
      Or
      You can use QUrl and then expose its setter getter using PROPERTY.
      ie.
      @
      Q_PROPERTY(QUrl imagePath READ imagePath WRITE setImagePath NOTIFY imagePathChanged)
      @
      and once the path is set from the QML element access it from the cpp and "load":http://qt-project.org/doc/qt-5.0/qtgui/qimage.html#load the image.

      157

      1 Reply Last reply
      0
      • G Offline
        G Offline
        gggfggg
        wrote on last edited by
        #3

        Thanks for your reply.

        I started investigating QQuickImageProvider, and request implementation with .fill() method works fine, but when I try to copy the part of an image (QImage or QPixmap) or just try to show the image on QML-form loading it either in request-method itself or before QQuickImageProvider initialization - I still have no result.

        @
        class MyProvider : public QQuickImageProvider
        {
        public:
        QPixmap SourcePixmap;
        MyProvider::MyProvider() : QQuickImageProvider( QQuickImageProvider::Pixmap )
        {
        SourcePixmap.load( "Source.png" );
        }
        QPixmap requestPixmap( const QString &id, QSize *size, const QSize &requestedSize )
        {
        int width = 80;
        int height = 80;
        if( size ) *size = QSize( width, height );
        QPixmap pixmap( requestedSize.width() > 0 ? requestedSize.width() : width,
        requestedSize.height() > 0 ? requestedSize.height() : height );

          // does not work
          pixmap = SourcePixmap.copy( 0, 0, width, height );
        
          /* does not work too
          pixmap.load( "Source80.png" ); */
          
          /* this works
          pixmap.fill( QColor( id ).rgba()); */
        
          return pixmap;
        

        }
        }
        @

        @
        int main( int argc, char *argv[])
        {
        ...
        QQuickView *viewer = new QQuickView;
        viewer -> engine() -> addImageProvider( QLatin1String( "myprovider" ), new MyProvider );
        ...
        }
        @

        @
        // main.qml
        ...
        Image { source: "image://myprovider" }
        ...
        @

        What am i doing wrong?

        [quote author="p3c0" date="1384962646"]Hi,
        You can use QUrl and then expose its setter getter using PROPERTY.
        ie.
        @
        Q_PROPERTY(QUrl imagePath READ imagePath WRITE setImagePath NOTIFY imagePathChanged)
        @
        and once the path is set from the QML element access it from the cpp and "load":http://qt-project.org/doc/qt-5.0/qtgui/qimage.html#load the image.[/quote]

        I didn't understand how can i use your idea with Qurl, as a part of the big image should be chosen randomly (that's why repeats are not very likely), it is not a set of pre-made images, which I form in a single image. I may have not enough knowlegde and experience in QML to understand your idea.

        I also wanted to ask what is better to use in my case - QImage or QPixmap - taking into account that downloading of a source takes place one time. After that very frequent copying of a random fragment, simple random transformation (horizontal/vertical flipping) and showing on QML-form are made.

        1 Reply Last reply
        0
        • S Offline
          S Offline
          stereomatching
          wrote on last edited by
          #4

          I don't know how to use QQuickImageProvider yet(any benefit(s) compare to QQuickPaintedItem?).But QQuickPaintedItem works well for me, you can't set the QImage as property directly, but you could provide QString as property without any problem.

          The full source codes of my custom image is a little bit complex
          Here is the code snippet
          @
          Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged);

          void customImage::setSource(QString source)
          {
          if(source != source_){
          source_ = source;
          imageOrigin_.load(source_);
          update(); //call paint

                  emit sourceChanged();        
          }
          

          }

          void customImage::paint(QPainter *painter)
          {
          //paint your image
          if(!img.isNull()){
          painter->drawImage((width() - imageScaled().width()) / 2,
          (height() - imageScaled().height()) / 2, img);
          }else{
          painter->drawImage((width() - imageScaled().width()) / 2,
          (height() - imageScaled().height()) / 2, imageScaled());
          }
          }
          @

          Therefore, you can use your qml component like this

          @
          customImage
          {
          source : "wwww.jpg"
          //other property
          }
          @

          1 Reply Last reply
          0
          • G Offline
            G Offline
            gggfggg
            wrote on last edited by
            #5

            Ok, i got the first result. It appeared that copying a part of a big image on timer signal should be done in request-method. I see the result of the first copying, but update() doesnt't repaint item. I call update in a slot of an item on timer from C++.

            Do you have an idea, what's wrong with this?

            @
            void MyItem::paint( QPainter *painter )
            {
            img = sourceImage.copy( x, y, 100, 100 );
            painter -> drawImage( QPoint(0,0), img );
            }

            void MyItem::myItem_update_Slot()
            {
            update();
            }
            @

            So, I don't use Q_PROPERTY, is it correct?

            1 Reply Last reply
            0
            • S Offline
              S Offline
              stereomatching
              wrote on last edited by
              #6

              Could you reproduce your problems with minimum lines of codes?

              1 Reply Last reply
              0
              • G Offline
                G Offline
                gggfggg
                wrote on last edited by
                #7

                [quote author="stereomatching" date="1385586192"]Could you reproduce your problems with minimum lines of codes?[/quote]

                There are ten lines of code.

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  stereomatching
                  wrote on last edited by
                  #8

                  [quote author="gggfggg" date="1385666236"][quote author="stereomatching" date="1385586192"]Could you reproduce your problems with minimum lines of codes?[/quote]

                  There are ten lines of code.[/quote]
                  What I mean is "please give me a full example which could reproduce your problem with minimum lines of codes" but not asking you "how many lines of codes you write".

                  if you want to call the c++ functions from qml site, you need to add Q_PROPERTY before the function or make them become public slots.

                  1 Reply Last reply
                  0
                  • E Offline
                    E Offline
                    eliseev
                    wrote on last edited by
                    #9

                    @gggfggg

                    1. What thread calls MyItem::myItem_update_Slot()? I had similarly sounding problem with update() when it was called from non-UI thread.
                    2. For test's sake put an animated object (e.g. flying rect) into your scene to force redrawing and see if scene updates (update content with timer at the same time).

                    @stereomatching
                    bq. if you want to call the c++ functions from qml site, you need to add Q_PROPERTY before the function or make them become public slots.
                    Correction, it's Q_INVOKABLE
                    But he doesn't need it.

                    1 Reply Last reply
                    0
                    • S Offline
                      S Offline
                      stereomatching
                      wrote on last edited by
                      #10

                      [quote author="Sergei Eliseev" date="1385743150"]@gggfggg

                      1. What thread calls MyItem::myItem_update_Slot()? I had similarly sounding problem with update() when it was called from non-UI thread.
                      2. For test's sake put an animated object (e.g. flying rect) into your scene to force redrawing and see if scene updates (update content with timer at the same time).

                      @stereomatching
                      bq. if you want to call the c++ functions from qml site, you need to add Q_PROPERTY before the function or make them become public slots.
                      Correction, it's Q_INVOKABLE
                      But he doesn't need it.[/quote]

                      Thanks for your correction, I didn't notice it

                      1 Reply Last reply
                      0
                      • G Offline
                        G Offline
                        gggfggg
                        wrote on last edited by
                        #11

                        [quote author="stereomatching" date="1385677858"]
                        What I mean is "please give me a full example which could reproduce your problem with minimum lines of codes"[/quote]
                        I thought you need less.

                        [quote author="Sergei Eliseev" date="1385743150"]
                        What thread calls MyItem::myItem_update_Slot()?[/quote]
                        MyItem::myItem_update_Slot() calls on timer signal. I don't use multi-threading in my code. Here I connect timer with update():
                        @
                        MyModel::MyModel( QObject *parent ) : QObject( parent )
                        {
                        myitem = new MyItem();
                        mytimer = new QTimer;
                        mytimer -> setInterval( 100 );
                        connect(mytimer, SIGNAL(timeout()), myitem, SLOT(myItem_update_Slot()));
                        mytimer -> start();
                        }
                        @
                        And the less of the code once again:
                        @
                        void MyItem::myItem_update_Slot()
                        {
                        x = rand() % 1400;
                        y = rand() % 1400;
                        j = rand() % 100;
                        k = rand() % 100;
                        update();
                        }

                        void MyItem::paint( QPainter *painter )
                        {
                        img = sourceImage.copy( x, y, 100, 100 );
                        painter -> drawImage( QPoint( j, k ), img );
                        // flying rect
                        // painter -> fillRect( j, k, 50, 50, Qt::black );
                        }

                        // main.qml
                        import QtQuick 2.0
                        import MyItem 1.0

                        Rectangle {
                        width: 360
                        height: 360
                        MyItem{
                        width: 300
                        height: 300
                        }
                        }
                        @
                        [quote author="Sergei Eliseev" date="1385743150"]
                        For test's sake put an animated object[/quote]
                        Thanks for the idea, I've checked it as demonstrated above (if I got it right). update() is being called, but repaint isn't done. I suspect that it can be related to the visibility scope of vars inside paint() during update() calling.

                        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