Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to animate/change color of QPixmap/QImage/QPicture/whatever on mouseEvents?
Forum Updated to NodeBB v4.3 + New Features

How to animate/change color of QPixmap/QImage/QPicture/whatever on mouseEvents?

Scheduled Pinned Locked Moved Solved General and Desktop
10 Posts 3 Posters 1.4k Views 2 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
    deleted385
    wrote on last edited by deleted385
    #1

    What I basically want is a button, with svg icon / path data, and without any text which will change color (animate) on enter, leave, press. Previously I tried with QAction, doesn't work, and here I've tried another approach with QWidget:

    ActionButton::ActionButton(const QString &fileName, QWidget *parent) :QWidget(parent){
        icon = QImage(fileName); // fileName.svg
        auto label = new QLabel();
        label->setPixmap(QPixmap::fromImage(icon));
        auto lay = new QVBoxLayout(this);
        lay->setContentsMargins(0,0,0,0);
        lay->addWidget(label);
        setLayout(lay);
    }
    void ActionButton::enterEvent(QEnterEvent *event){
        qDebug() << "entered";
        icon.fill(Qt::blue);
    }
    void ActionButton::leaveEvent(QEvent *event){
        qDebug() << "left";
        icon.fill(Qt::black);
    }
    void ActionButton::mousePressEvent(QMouseEvent *event){
        qDebug() << "pressed";
        icon.fill(Qt::red);
    }
    

    it detects correctly the enter, leave and press BUT doesn't change color. It also doesn't resize the image when I reset label width and height.

    EDIT
    Like this:
    x1.gif

    eyllanescE JKSHJ 2 Replies Last reply
    0
    • eyllanescE eyllanesc

      @Emon-Haque share the .svg

      eyllanescE Offline
      eyllanescE Offline
      eyllanesc
      wrote on last edited by
      #5

      @eyllanesc You have to modify the svg attributes for example using QtXml

      #include <QApplication>
      #include <QDomDocument>
      #include <QEnterEvent>
      #include <QFile>
      #include <QLabel>
      #include <QPainter>
      #include <QSvgRenderer>
      #include <QVBoxLayout>
      #include <QWidget>
      
      #include <QDebug>
      
      class ActionButton: public QWidget{
      public:
          ActionButton(const QString & filename, QWidget *parent=nullptr)
              :QWidget(parent), m_label(new QLabel)
          {
              m_label->setAlignment(Qt::AlignCenter);
              QVBoxLayout *lay = new QVBoxLayout(this);
              lay->addWidget(m_label);
              QFile f(filename);
              if(f.open(QIODevice::ReadOnly | QIODevice::Text)){
                  m_document.setContent(f.readAll());
              }
              changeColor(QColor("red"));
          }
      protected:
          void enterEvent(QEvent *event)
          {
              QWidget::enterEvent(event);
              qDebug() << "entered";
              changeColor(Qt::blue);
          }
          void leaveEvent(QEvent *event){
              QWidget::leaveEvent(event);
              qDebug() << "left";
              changeColor(Qt::black);
          }
          void mousePressEvent(QMouseEvent *event){
              QWidget::mousePressEvent(event);
              qDebug() << "pressed";
              changeColor(Qt::red);
          }
      private:
          void changeColor(const QColor & color){
              QDomNodeList  path_elements = m_document.elementsByTagName("path");
              if(path_elements.length() > 0){
                  QDomNode path_node = path_elements.at(0);
                  if(path_node.isElement()){
                      QDomElement path_element = path_node.toElement();
                      path_element.setAttribute("fill", color.name());
                  }
              }
              m_renderer.load(m_document.toByteArray());
              QPixmap pixmap(m_renderer.defaultSize());
              pixmap.fill(Qt::transparent);
              QPainter painter(&pixmap);
              m_renderer.render(&painter);
              painter.end();
              m_label->setPixmap(pixmap);
          }
          QSvgRenderer m_renderer;
          QDomDocument m_document;
          QLabel *m_label;
      };
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
          QString filename{"/path/of/database-plus.svg"};
          ActionButton button(filename);
          button.show();
          return a.exec();
      }
      

      If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

      D 1 Reply Last reply
      4
      • D deleted385

        What I basically want is a button, with svg icon / path data, and without any text which will change color (animate) on enter, leave, press. Previously I tried with QAction, doesn't work, and here I've tried another approach with QWidget:

        ActionButton::ActionButton(const QString &fileName, QWidget *parent) :QWidget(parent){
            icon = QImage(fileName); // fileName.svg
            auto label = new QLabel();
            label->setPixmap(QPixmap::fromImage(icon));
            auto lay = new QVBoxLayout(this);
            lay->setContentsMargins(0,0,0,0);
            lay->addWidget(label);
            setLayout(lay);
        }
        void ActionButton::enterEvent(QEnterEvent *event){
            qDebug() << "entered";
            icon.fill(Qt::blue);
        }
        void ActionButton::leaveEvent(QEvent *event){
            qDebug() << "left";
            icon.fill(Qt::black);
        }
        void ActionButton::mousePressEvent(QMouseEvent *event){
            qDebug() << "pressed";
            icon.fill(Qt::red);
        }
        

        it detects correctly the enter, leave and press BUT doesn't change color. It also doesn't resize the image when I reset label width and height.

        EDIT
        Like this:
        x1.gif

        eyllanescE Offline
        eyllanescE Offline
        eyllanesc
        wrote on last edited by
        #2

        @Emon-Haque share the .svg

        If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

        D eyllanescE 2 Replies Last reply
        1
        • eyllanescE eyllanesc

          @Emon-Haque share the .svg

          D Offline
          D Offline
          deleted385
          wrote on last edited by deleted385
          #3

          @eyllanesc, I use this site for path data/svg icons. Right click on any icon, click Download .SVG Compressed on the context menu, you'll get the svg file that works fine in Qt.

          1 Reply Last reply
          0
          • D deleted385

            What I basically want is a button, with svg icon / path data, and without any text which will change color (animate) on enter, leave, press. Previously I tried with QAction, doesn't work, and here I've tried another approach with QWidget:

            ActionButton::ActionButton(const QString &fileName, QWidget *parent) :QWidget(parent){
                icon = QImage(fileName); // fileName.svg
                auto label = new QLabel();
                label->setPixmap(QPixmap::fromImage(icon));
                auto lay = new QVBoxLayout(this);
                lay->setContentsMargins(0,0,0,0);
                lay->addWidget(label);
                setLayout(lay);
            }
            void ActionButton::enterEvent(QEnterEvent *event){
                qDebug() << "entered";
                icon.fill(Qt::blue);
            }
            void ActionButton::leaveEvent(QEvent *event){
                qDebug() << "left";
                icon.fill(Qt::black);
            }
            void ActionButton::mousePressEvent(QMouseEvent *event){
                qDebug() << "pressed";
                icon.fill(Qt::red);
            }
            

            it detects correctly the enter, leave and press BUT doesn't change color. It also doesn't resize the image when I reset label width and height.

            EDIT
            Like this:
            x1.gif

            JKSHJ Offline
            JKSHJ Offline
            JKSH
            Moderators
            wrote on last edited by JKSH
            #4

            @Emon-Haque said in How to animate/change color of QPixmap/QImage/QPicture/whatever on mouseEvents?:

            doesn't resize the image when I reset label width and height

            QImage and QPixmap are fixed size. You can update the size by calling QImage::scaled() or QPixmap::scaled(), but you will get pixellation.

            If you want resizable SVG, use QSvgWidget instead. Update the size by calling QSvgWidget::resize() -- the SVG will be rendered at the new size without pixellation.

            doesn't change color

            2 important notes:

            • Your code only updates icon. You also need to update label -- these are 2 separate copies of your image.
            • QImage::fill() fills the entire image with a solid colour. It doesn't change the colour of an existing image.

            Unfortunately, there is no straightforward way to animate colours in a QLabel or QSvgWidget. The alternatives are:

            • Put your icon in a QGraphicsView and apply a QGraphicsColorizeEffect (see https://doc.qt.io/qt-5/qgraphicseffect.html )
            • Implement your GUI in QML and apply a Colorize effect (see https://doc.qt.io/qt-5/qml-qtgraphicaleffects-colorize.html )

            Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

            D 1 Reply Last reply
            3
            • eyllanescE eyllanesc

              @Emon-Haque share the .svg

              eyllanescE Offline
              eyllanescE Offline
              eyllanesc
              wrote on last edited by
              #5

              @eyllanesc You have to modify the svg attributes for example using QtXml

              #include <QApplication>
              #include <QDomDocument>
              #include <QEnterEvent>
              #include <QFile>
              #include <QLabel>
              #include <QPainter>
              #include <QSvgRenderer>
              #include <QVBoxLayout>
              #include <QWidget>
              
              #include <QDebug>
              
              class ActionButton: public QWidget{
              public:
                  ActionButton(const QString & filename, QWidget *parent=nullptr)
                      :QWidget(parent), m_label(new QLabel)
                  {
                      m_label->setAlignment(Qt::AlignCenter);
                      QVBoxLayout *lay = new QVBoxLayout(this);
                      lay->addWidget(m_label);
                      QFile f(filename);
                      if(f.open(QIODevice::ReadOnly | QIODevice::Text)){
                          m_document.setContent(f.readAll());
                      }
                      changeColor(QColor("red"));
                  }
              protected:
                  void enterEvent(QEvent *event)
                  {
                      QWidget::enterEvent(event);
                      qDebug() << "entered";
                      changeColor(Qt::blue);
                  }
                  void leaveEvent(QEvent *event){
                      QWidget::leaveEvent(event);
                      qDebug() << "left";
                      changeColor(Qt::black);
                  }
                  void mousePressEvent(QMouseEvent *event){
                      QWidget::mousePressEvent(event);
                      qDebug() << "pressed";
                      changeColor(Qt::red);
                  }
              private:
                  void changeColor(const QColor & color){
                      QDomNodeList  path_elements = m_document.elementsByTagName("path");
                      if(path_elements.length() > 0){
                          QDomNode path_node = path_elements.at(0);
                          if(path_node.isElement()){
                              QDomElement path_element = path_node.toElement();
                              path_element.setAttribute("fill", color.name());
                          }
                      }
                      m_renderer.load(m_document.toByteArray());
                      QPixmap pixmap(m_renderer.defaultSize());
                      pixmap.fill(Qt::transparent);
                      QPainter painter(&pixmap);
                      m_renderer.render(&painter);
                      painter.end();
                      m_label->setPixmap(pixmap);
                  }
                  QSvgRenderer m_renderer;
                  QDomDocument m_document;
                  QLabel *m_label;
              };
              
              int main(int argc, char *argv[])
              {
                  QApplication a(argc, argv);
                  QString filename{"/path/of/database-plus.svg"};
                  ActionButton button(filename);
                  button.show();
                  return a.exec();
              }
              

              If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

              D 1 Reply Last reply
              4
              • JKSHJ JKSH

                @Emon-Haque said in How to animate/change color of QPixmap/QImage/QPicture/whatever on mouseEvents?:

                doesn't resize the image when I reset label width and height

                QImage and QPixmap are fixed size. You can update the size by calling QImage::scaled() or QPixmap::scaled(), but you will get pixellation.

                If you want resizable SVG, use QSvgWidget instead. Update the size by calling QSvgWidget::resize() -- the SVG will be rendered at the new size without pixellation.

                doesn't change color

                2 important notes:

                • Your code only updates icon. You also need to update label -- these are 2 separate copies of your image.
                • QImage::fill() fills the entire image with a solid colour. It doesn't change the colour of an existing image.

                Unfortunately, there is no straightforward way to animate colours in a QLabel or QSvgWidget. The alternatives are:

                • Put your icon in a QGraphicsView and apply a QGraphicsColorizeEffect (see https://doc.qt.io/qt-5/qgraphicseffect.html )
                • Implement your GUI in QML and apply a Colorize effect (see https://doc.qt.io/qt-5/qml-qtgraphicaleffects-colorize.html )
                D Offline
                D Offline
                deleted385
                wrote on last edited by
                #6

                @JKSH, I've QT += core gui svg in .pro. When I add #include <QSvgWidget> in .h file I get QSvgWidget file not found. How to fix that?

                eyllanescE 1 Reply Last reply
                0
                • D deleted385

                  @JKSH, I've QT += core gui svg in .pro. When I add #include <QSvgWidget> in .h file I get QSvgWidget file not found. How to fix that?

                  eyllanescE Offline
                  eyllanescE Offline
                  eyllanesc
                  wrote on last edited by
                  #7

                  @Emon-Haque what is your Qt version?

                  If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

                  D 1 Reply Last reply
                  0
                  • eyllanescE eyllanesc

                    @Emon-Haque what is your Qt version?

                    D Offline
                    D Offline
                    deleted385
                    wrote on last edited by
                    #8

                    @eyllanesc, 6.2.0

                    eyllanescE 1 Reply Last reply
                    0
                    • D deleted385

                      @eyllanesc, 6.2.0

                      eyllanescE Offline
                      eyllanescE Offline
                      eyllanesc
                      wrote on last edited by
                      #9

                      @Emon-Haque Please read the docs: https://doc.qt.io/qt-6/qsvgwidget.html, add

                      QT += svgwidgets
                      

                      If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

                      1 Reply Last reply
                      2
                      • eyllanescE eyllanesc

                        @eyllanesc You have to modify the svg attributes for example using QtXml

                        #include <QApplication>
                        #include <QDomDocument>
                        #include <QEnterEvent>
                        #include <QFile>
                        #include <QLabel>
                        #include <QPainter>
                        #include <QSvgRenderer>
                        #include <QVBoxLayout>
                        #include <QWidget>
                        
                        #include <QDebug>
                        
                        class ActionButton: public QWidget{
                        public:
                            ActionButton(const QString & filename, QWidget *parent=nullptr)
                                :QWidget(parent), m_label(new QLabel)
                            {
                                m_label->setAlignment(Qt::AlignCenter);
                                QVBoxLayout *lay = new QVBoxLayout(this);
                                lay->addWidget(m_label);
                                QFile f(filename);
                                if(f.open(QIODevice::ReadOnly | QIODevice::Text)){
                                    m_document.setContent(f.readAll());
                                }
                                changeColor(QColor("red"));
                            }
                        protected:
                            void enterEvent(QEvent *event)
                            {
                                QWidget::enterEvent(event);
                                qDebug() << "entered";
                                changeColor(Qt::blue);
                            }
                            void leaveEvent(QEvent *event){
                                QWidget::leaveEvent(event);
                                qDebug() << "left";
                                changeColor(Qt::black);
                            }
                            void mousePressEvent(QMouseEvent *event){
                                QWidget::mousePressEvent(event);
                                qDebug() << "pressed";
                                changeColor(Qt::red);
                            }
                        private:
                            void changeColor(const QColor & color){
                                QDomNodeList  path_elements = m_document.elementsByTagName("path");
                                if(path_elements.length() > 0){
                                    QDomNode path_node = path_elements.at(0);
                                    if(path_node.isElement()){
                                        QDomElement path_element = path_node.toElement();
                                        path_element.setAttribute("fill", color.name());
                                    }
                                }
                                m_renderer.load(m_document.toByteArray());
                                QPixmap pixmap(m_renderer.defaultSize());
                                pixmap.fill(Qt::transparent);
                                QPainter painter(&pixmap);
                                m_renderer.render(&painter);
                                painter.end();
                                m_label->setPixmap(pixmap);
                            }
                            QSvgRenderer m_renderer;
                            QDomDocument m_document;
                            QLabel *m_label;
                        };
                        
                        int main(int argc, char *argv[])
                        {
                            QApplication a(argc, argv);
                            QString filename{"/path/of/database-plus.svg"};
                            ActionButton button(filename);
                            button.show();
                            return a.exec();
                        }
                        
                        D Offline
                        D Offline
                        deleted385
                        wrote on last edited by
                        #10

                        @eyllanesc, hmm not bad:

                        x1.gif

                        would be nicer if there's some easy way to add a QPropertyAnimation for color. Instead of svg file there should be some way to use path data, to avoid DOM traversing, directly and animate its color.

                        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