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. QToolTip::showText not showing - Mouse event ?

QToolTip::showText not showing - Mouse event ?

Scheduled Pinned Locked Moved Unsolved General and Desktop
qtooltipqvalidatormouse event
5 Posts 2 Posters 1.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.
  • T Offline
    T Offline
    TheFarman
    wrote on last edited by TheFarman
    #1

    Hello,

    I'm trying to do a Validator that can notify when input is Invalid or Intermediate. Therefor I emit a custom signal that contain the notification message:

    void Validator::fixup(QString& input) const
    {
        Fixup(input);
        if (options.testFlag(Option::SendAtFixup) == true)
        {
            qDebug() << "FixUp";
            emit Error(ErrorMessage());
        }
    }
    
    Validator::State Validator::validate(QString& input, int& pos) const
    {
        State state = Validate(input, pos);
    
        if (options.testFlag(Option::SendDurringValidation) == true)
        {
            switch (state)
            {
            case State::Invalid :
                qDebug() << "Validate";
                emit Error(ErrorMessage());
                break;
            case State::Intermediate :
                break;
            case State::Acceptable :
                break;
            }
        }
        return state;
    }
    
    QString Validator::ErrorMessage() const
    {
        return ErrorStart + QString("Error") + ErrorEnd;
    }
    

    Then on my LineEdit using Validator I connect the signal Validator::Error to a custom slot LineEdit::ShowMessage to display the message as a ToolTip:

    void LineEdit::ShowMessage(const QString& message)
    {
        int halfWidth = rect().width() * 0.5f;
        int halfHeight = rect().height() * 0.5f;
    
        QPoint tooltipPos = mapToGlobal(pos());
    
        tooltipPos.rx() += halfWidth;
        tooltipPos.ry() -= halfHeight;
    
        QToolTip::showText(tooltipPos, message, this);
    }
    

    It works well when used from Validator::validate or when called from Validator::fixup if the user pressed Enter/Return:
    Error.png

    Howerver, it does not work when clicking provokes a focus lost:
    Losing focus calls Validator::fixup which emit the signal that triggersLineEdit::ShowMessage but the ToolTip is not shown.
    I first thought that is was because LineEdit did not have focus when the QToolTip::showText was called. Therefor, I overrode the focusOut method:

    void LineEdit::focusOutEvent(QFocusEvent* focusEvent)
    {
        (void)focusEvent;
        if (hasAcceptableInput() == false)
        {
            setFocus();
            QString invalidInupt = text();
            validator()->fixup(invalidInupt);
        }
    }
    

    Here LineEdit has focus but the ToolTip is still not shown. My last guess is that a mouse event, probably the clicking, prevents the ToolTip.
    Any ideas on whether or not I'm on the right track and if so, how to do it properly? Thank you

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

      Hi and welcome to devnet,

      Did you check whether the position is valid and within your widget ?

      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
      • T Offline
        T Offline
        TheFarman
        wrote on last edited by
        #3

        Hi thank you,

        Well it is the same slot as the other working cases that are correctly showing the tooltip (on the picture) so I assume yes ?

        1 Reply Last reply
        0
        • T Offline
          T Offline
          TheFarman
          wrote on last edited by
          #4

          I've made it work somewhat, but there are 2 remaining problems (actually one was not yet identified in the original post):

          First, I decided to use QWidget::mouseGrab when LineEdit gain focus:

          void LineEdit::focusInEvent(QFocusEvent* focusEvent)
          {
              grabMouse();
              QLineEdit::focusInEvent(focusEvent);
          }
          

          That leads to being unable to lose focus by cliking (obviously).
          So, I needed to implement LineEdit::mousePressEvent to know what to do:

          • When cliking inside the LineEdit: behave as normal

          • When cliking on other widget: use QLineEdit::hasAcceptableInput to verify input.
            If input is valid -> release the mouse and set focus on other widget;
            Else -> manualy call QValidator::fixup from QLineEdit::validator (that will trigger the message to be shown).

          • When clicking anywhere else is the same as clicking on other widget except that the focus is cleared instead.

          Actualy, this was kind of working but the tooltip was only shown when the mouse button was being pressed: upon release, the tooltip would hide itself.
          (I belive any mouse event prevent the tooltip to be shown in this case as the cursor is outside the widget).
          So I ended up moving this in LineEdit::mouseReleaseEvent. Here is a simplified version:

          void LineEdit::mouseReleaseEvent(QMouseEvent* event)
          {
              if (UnderMouse(event->globalPos()) == true) // Check if LineEdit is under cursor
              {
                  QLineEdit::mouseReleaseEvent(event);
                  return;
              }
          
              if (hasAcceptableInput() == false)
              {
                  FixInput(); // Helper method to call validator()->fixup(copiedText) (trigger will show the tooltip)
                  return;
              }
              else
              {
                  releaseMouse();
                  clearFocus();
                  return;
              }    
          }
          

          (There is still a similar first 'if-block' in LineEdit::mousePressEvent to prevent mousePressEvent to do something if not 'mouse-pressing' inside the LineEdit)

          This work as I want to, except the 2 following problems :

          1. It prevent the user to click on the window frame buttons since mouse events are intercepted.
          2. Using Tab key still allows to give focus to next widget, again the QValidator::fixup is indeed called, but the tooltip is not showing.

          First Problem (Just my insight on the problem but I think I can mange, you can skip to next pb if you want to help ☺):
          Idealy, I would have to override LineEdit::mouseMoveEvent and do something (involving releasing the mouse) when hovering the main frame so the user can interact with the buttons. But it would still needs to re-grab the mouse if the cursor goes back inside the window. That part should be doable with a bit of work, I'm not to concerned right now.

          Second Problem ('Real' problem):
          Sadly using focus policy Qt::ClickFocus does not prevent Leaving with keyboard, it just prevent Entering with keyboard.
          So, as with the mouse, I tried to grab the keyboard LineEdit gain focus and just debug the key pressed in LineEdit::keyPressEvent but this method was not called. So, I guess this is not a Keyboard Event? maybe a Shortcut Event ? If not I have no more idea. I will try Shortcut Event soon.

          1 Reply Last reply
          0
          • T Offline
            T Offline
            TheFarman
            wrote on last edited by TheFarman
            #5

            Tab problem is solved !

            I don't think it is a Shortcut Event as StandardKey of QKeySequence does not map Tab key. I don't realy know how it is done inside Qt, I might search later.

            I actualy just overrode QLineEdit::focusNextPreviousChild to do a validation check:

            bool LineEdit::focusNextPrevChild(bool next)
            {
                if (hasAcceptableInput() == false)
                {
                    FixInput();
                    return true; // To prevent searching for other widgets
                }
            
                return QLineEdit::focusNextPrevChild(next);
            }
            

            As a result, if input is invalid when the user press Tab the tooltip is shown but if the input is valid the next widget gain focus
            Error2.png

            Apparently I still need to have better accuracy for the position of the tooltip though
            EDIT: QWidget::mapToGlobal already include the position of the widget (should have been obvious) So I just changed mapToGlobal(pos()); to mapToGlobal(s_zero); with static const QPoint s_zero = QPoint(0, 0)

            1 Reply Last reply
            1

            • Login

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