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. [SOLVED] Making QLabel hover-aware
QtWS25 Last Chance

[SOLVED] Making QLabel hover-aware

Scheduled Pinned Locked Moved General and Desktop
12 Posts 3 Posters 16.9k 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.
  • I Offline
    I Offline
    i92guboj
    wrote on last edited by
    #1

    Hi.

    I am trying to make a QLabel subclass react to a mouse hover action. What I want to achieve is a magnifying glass effect over a QLabel, but first thing first...

    I have already made it clickable, but I can't figure how to implement the hovering part. Should I be using the mouseMoveEvent() or am I looking in the wrong direction? It doesn't seem to react to that...

    [code]
    void myLabel::mouseMoveEvent(QMouseEvent *event)
    {
    Q_UNUSED(event);
    qDebug() << Q_FUNC_INFO << QString("This thing is being hovered");
    emit hovered();
    }
    [/code]

    1 Reply Last reply
    0
    • T Offline
      T Offline
      thEClaw
      wrote on last edited by
      #2

      I can't give you a perfect solution, but a while ago I tried to achieve the same thing.

      Solution 1: Use a "QTimer":http://qt-project.org/doc/qt-5.1/qtcore/qtimer.html . I made it so that about every 50ms (should depend on the size of the label, too big of a delay doesn't feel good) the program checked if the mouse was actually hovering over a magnifiable label. If so, the label was magnified.

      Solution 2: Reimplement the enterEvent() of the label and emit a signal from within. Use that signal somehow to magnify things. I had to use a protective timer in addition, so the magnification wouldn't be launched more than once when moving the mouse rapidly.

      I think you may need to activate mouseTracking for the second solution to work.

      1 Reply Last reply
      0
      • I Offline
        I Offline
        i92guboj
        wrote on last edited by
        #3

        Hello again.

        And sorry for the delay, real life has kept me a bit busy lately.

        I will be checking both options and report back how it worked (or not) out. Thank you for the suggestions. :)

        1 Reply Last reply
        0
        • I Offline
          I Offline
          i92guboj
          wrote on last edited by
          #4

          So far, it seems to work, and it doesn't interfere with the clicked() signal which I also implemented and is being used for some other thing:

          @#include "mylabel.h"
          #include <QDebug>
          #include <QToolButton>

          myLabel::myLabel(QWidget * parent )
          :QLabel(parent)
          {
          connect( this, SIGNAL( clicked() ), this, SLOT( slotClicked() ) );
          setMouseTracking(true);
          }

          void myLabel::slotClicked()
          {
          qDebug()<<"Clicked";
          }

          void myLabel::mousePressEvent ( QMouseEvent * event )
          {
          Q_UNUSED(event);
          emit clicked();
          }

          void myLabel::mouseMoveEvent(QMouseEvent *event)
          {
          Q_UNUSED(event);
          qDebug() << Q_FUNC_INFO << QString("This thing is being hovered");
          emit hovered();
          }

          void myLabel::resizeEvent(QResizeEvent *event) {
          QWidget::resizeEvent(event);
          resizeImage();
          }

          void myLabel::resizeImage() {
          if(this->pixmap() != NULL)
          {
          qDebug() << Q_FUNC_INFO << QString("El tamaño de este widget es %1, %2").arg(size().width()).arg(size().height());
          setPixmap(pixmap()->scaled(size(), Qt::KeepAspectRatio/ByExpanding/, Qt::SmoothTransformation));
          }
          }

          void myLabel::enterEvent(QEvent *event)
          {
          qDebug() << Q_FUNC_INFO << "enter event triggered!";
          QLabel::enterEvent(event);
          }@

          When mouse tracking is enabled, the thing is triggered as I move, so this seems perfect for my purpose. Now I just have to figure how to cut a portion of the original image matching the mouse position in the miniature to redraw the pixmap as I move the mouse, but that's another story.

          I guess this is solved, I'll come back if I find some show stopper in the way. Thank you :)

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            Hi,

            Did you try with
            @setAttribute(Qt::WA_Hover);@

            and reimplement event to handle the HoverEnter, HoverMove and HoverLeave ?

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            0
            • I Offline
              I Offline
              i92guboj
              wrote on last edited by
              #6

              YOU CAN IGNORE THIS, IT WAS A SILLY ERROR IN MY SIDE

              I am still working in the solution proposed above. So far, mouseMoveEvent() seems to be working but there's one problem I cannot understand. And it's that the hovered() signals doesn't seem to ever get emitted.

              In the principal class of my program I am connecting that signal to a method that will handle all the zoom on hover stuff, but that method never gets called, or so it seems.

              The signal is now emitted this way:

              @void myLabel::mouseMoveEvent(QMouseEvent *event)
              {
              //Q_UNUSED(event);
              qDebug() << Q_FUNC_INFO << QString("This thing is being hovered");
              double xpos = 100./width()*event->posF().x();
              double ypos = 100./height()*event->posF().y();
              //qDebug() << Q_FUNC_INFO << QString("position within this: %1 x %2").arg(xpos).arg(ypos);
              emit hovered(xpos, ypos);
              }@

              So that it will hold the coordinates (as percentages), which will be useful when calculating which part of the image is to be zoomed.

              Then, from the constructor of the main class I connect it this way:

              @ connect(ui->gv_foto_medio, SIGNAL(hovered(double,double)), this, SLOT(raton_sobre_foto_mediana(double,double)));@

              And the slot is:

              @void kooker::raton_sobre_foto_mediana(double xpos, double ypos)
              {
              qDebug() << Q_FUNC_INFO << QString("position within this: %1 x %2").arg(xpos).arg(ypos);
              }@

              But this message is never output. Setting a breakpoint at that method indeed shows that it's never called. qtcreator doesn't show any error telling me that the connection is incorrect, so that's not it. The only thing I can assume is that the signal never gets emitted, but why?

              1 Reply Last reply
              0
              • I Offline
                I Offline
                i92guboj
                wrote on last edited by
                #7

                Please, completely disregard the above. I was connecting the wrong widget (I really need to do some cleaning). This made me lose some precious hours ;)

                SGaist, is there any advantage on the method you are describing over the current approach I am taking?

                I am looking for the simplest way to do this, and I am a bit surprised that there's no simple and straight way to detect hovering (at least on this concrete widget) in Qt (still using 4.8 here ;) ).

                Thank you everyone for all the help :)

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  Using this method, you really get the hover related events without the need to manipulate the mouse tracking and simulate the hovering part.

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0
                  • I Offline
                    I Offline
                    i92guboj
                    wrote on last edited by
                    #9

                    [quote author="SGaist" date="1381009111"]Using this method, you really get the hover related events without the need to manipulate the mouse tracking and simulate the hovering part.[/quote]

                    I hadn't found about this before. I'll definitely put that in my to-do list, but right now I have some other priorities regarding this project. Thank you for the information :)

                    1 Reply Last reply
                    0
                    • I Offline
                      I Offline
                      i92guboj
                      wrote on last edited by
                      #10

                      Sgaist, I got the time to look into this. It really helped in making this much more readable, quite a few lines of code that I removed. I could also take rid of a few reimplemented members.

                      However, there's a small glitch, and a somewhat strange one. I have this, as per your advice:

                      @
                      bool myLabel::event(QEvent *e)
                      {
                      QMouseEvent me = static_cast<QMouseEvent>(e);

                      if(e->type() == QEvent::HoverMove)
                      {
                          double xpos = me->pos().x();
                          double ypos = me->pos().y();
                          emit hovered(xpos, ypos);
                          qDebug() << Q_FUNC_INFO << QString("xpos %1, ypos %2").arg(xpos).arg(ypos);
                          return true;
                      }
                      else if(e->type() == QEvent::HoverLeave)
                      {
                          emit unhovered();
                          return true;
                      }
                      else if(e->type() == QEvent::MouseButtonPress)
                      {
                          emit clicked();
                          return true;
                      }
                      else if(e->type() == QEvent::MouseButtonDblClick)
                      {
                          emit doubleClicked();
                          return true;
                      }
                      
                      return QLabel::event(e);
                      

                      }
                      @

                      I do this in the constructor for this class:

                      @ setAttribute(Qt::WA_Hover);@

                      But now I am getting this in qDebug()'s output when I hover from down to up:

                      @
                      virtual bool myLabel::event(QEvent*) "xpos 40, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 39, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 38, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 37, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 36, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 34, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 33, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 31, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 30, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 29, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 28, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 27, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 26, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 25, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 24, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 23, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 22, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 21, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 20, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 18, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 17, ypos 39"
                      virtual bool myLabel::event(QEvent*) "xpos 15, ypos 40"
                      virtual bool myLabel::event(QEvent*) "xpos 14, ypos 40"
                      virtual bool myLabel::event(QEvent*) "xpos 12, ypos 40"
                      virtual bool myLabel::event(QEvent*) "xpos 11, ypos 40"
                      virtual bool myLabel::event(QEvent*) "xpos 10, ypos 40"
                      virtual bool myLabel::event(QEvent*) "xpos 9, ypos 40"
                      virtual bool myLabel::event(QEvent*) "xpos 8, ypos 40"
                      virtual bool myLabel::event(QEvent*) "xpos 7, ypos 40"
                      virtual bool myLabel::event(QEvent*) "xpos 6, ypos 40"
                      virtual bool myLabel::event(QEvent*) "xpos 4, ypos 40"
                      virtual bool myLabel::event(QEvent*) "xpos 2, ypos 40"
                      virtual bool myLabel::event(QEvent*) "xpos 1, ypos 40"
                      virtual bool myLabel::event(QEvent*) "xpos 0, ypos 40"
                      @

                      This worked before, and I have checked that's not something silly, plus, the numbers (according to the dimensions of the widget) seem to indicate that pos.x() and pos.y() values for the casted QMouseEvent are swapped.

                      In fact, if I emit unhovered(posy, posx), everything's back to normal. But......

                      Can you think of any reason why x() and y() values could be swapped like that?

                      In any case, thanks for the suggestion. It helped to simplify this quite a bit ;)

                      1 Reply Last reply
                      0
                      • SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        Maybe because you cast to a QMouseEvent rather than a QHoverEvent ?

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        1 Reply Last reply
                        0
                        • I Offline
                          I Offline
                          i92guboj
                          wrote on last edited by
                          #12

                          That was it, yes. It would have been hard to figure that myself. Thank you again :)

                          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