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. Popup and pushButton - how to solve it
QtWS25 Last Chance

Popup and pushButton - how to solve it

Scheduled Pinned Locked Moved Unsolved General and Desktop
18 Posts 2 Posters 2.7k 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
    TomNow99
    wrote on last edited by
    #1

    Hello,

    I have a QPushButton. When I click on it I would like to create QDialog, which has set flags:
    Qt::Window
    Qt::Popup
    Qt::FramelessWindowHin

    I set geometry of this QDialog under QPushButton ( it looks like QComboBox when I click QPushButton ).

    And this works perfect.

    But...

    I can't write good solution to hide this QDialog.

    There are possibilities:

    1. click ESCAPE - this works
    2. click somewhere outside the QPushButton and QDialog - this works
    3. click on the QPushButton - this works, but often with errors

    My goal:
    The first click QPushButton to show QDialog, next click to hide it, next click to show it. It looks very easy - I can have a static variable and do something like:

    if( variable % 2 == 0  )
    {
    
    }
    else
    {
    
    }
    

    But the problem is when I click outside the QPushButton. Then my variable don't change.

    I check and I see that when I set focus on QDialog and when I click outside the QPushButton it will be run only QFocusOutEvent. When I click on QPushButton it will be run both QFocusOutEvent and next mousePressEvent.

    I try using other variables, using exec and I don't have idea...

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

      Hi
      You can set an event filter on the dialog and look for the focus out event and then call
      reject() to close it. This allows you to capture "clicking outside the dialog"

      https://doc.qt.io/qt-5/eventsandfilters.html
      section Event Filters

      Make sure to read
      "it can accept or reject the event, and allow or deny further processing of the event. "
      and understand this part as else you will eats its event and it will do odd stuff.

      1 Reply Last reply
      1
      • T Offline
        T Offline
        TomNow99
        wrote on last edited by TomNow99
        #3

        @mrjj Thank you.

        I tried get the position of mouse cursor where it is when I clicked and I compare position with button's position. I know where the user clicked. But when I go to focus out event the widget is already hide ( popup -> focus out ), so I don't have to use reject.

        Sometimes when I click double times in a row I have situation in the end of queue events ( after the first click )

        focus out -> mouse press event

        Sometimes I have only:

        focus out

        So there is no the second click. And this is the problem.

        mrjjM 1 Reply Last reply
        0
        • T TomNow99

          @mrjj Thank you.

          I tried get the position of mouse cursor where it is when I clicked and I compare position with button's position. I know where the user clicked. But when I go to focus out event the widget is already hide ( popup -> focus out ), so I don't have to use reject.

          Sometimes when I click double times in a row I have situation in the end of queue events ( after the first click )

          focus out -> mouse press event

          Sometimes I have only:

          focus out

          So there is no the second click. And this is the problem.

          mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by mrjj
          #4

          @TomNow99
          Hi
          QComboxBox can do it with a local event filter so i wonder if it does use grabmouse.

          other also had this idea
          https://forum.qt.io/topic/97345/how-to-detect-mouse-click-outside-of-widget/2

          Here they set the event filter on QApp to allow to get all events.

          You could also use GrabMouse but be careful with that.

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

            @mrjj
            I find that my problem is the bug:
            https://bugreports.qt.io/browse/QTBUG-50051

            There is a solution, but I don't have source code to qpushButton. How can I solve that?

            mrjjM 1 Reply Last reply
            0
            • T TomNow99

              @mrjj
              I find that my problem is the bug:
              https://bugreports.qt.io/browse/QTBUG-50051

              There is a solution, but I don't have source code to qpushButton. How can I solve that?

              mrjjM Offline
              mrjjM Offline
              mrjj
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @TomNow99
              Hi
              The source code of can be installed with the maintenance tool.

              1 Reply Last reply
              0
              • T Offline
                T Offline
                TomNow99
                wrote on last edited by TomNow99
                #7

                @mrjj I find it here:
                https://code.woboq.org/qt5/qtbase/src/widgets/widgets/qpushbutton.cpp.html

                I find that function which I have to replace

                void QPushButtonPrivate::_q_popupPressed()

                But the problem is that I need class QPushButtonPrivate. Of course I find that too. But when I check QPushButtonPrivate I saw that I need QMenu and QMenuPrivate. I think there is better way to replace that QPushButtonPrivate function.

                EDIT:
                Of course I can have new class like QPushButton2. I don't need change QPushButton

                mrjjM 1 Reply Last reply
                0
                • T TomNow99

                  @mrjj I find it here:
                  https://code.woboq.org/qt5/qtbase/src/widgets/widgets/qpushbutton.cpp.html

                  I find that function which I have to replace

                  void QPushButtonPrivate::_q_popupPressed()

                  But the problem is that I need class QPushButtonPrivate. Of course I find that too. But when I check QPushButtonPrivate I saw that I need QMenu and QMenuPrivate. I think there is better way to replace that QPushButtonPrivate function.

                  EDIT:
                  Of course I can have new class like QPushButton2. I don't need change QPushButton

                  mrjjM Offline
                  mrjjM Offline
                  mrjj
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  @TomNow99
                  Hi
                  well in other cases you would apply the patch to Qt source and rebuild
                  the Widget Module. But for such small thing, im not sure its worth it.

                  Did you try with event filer on Application instead?
                  That should work.
                  Or use grabmouse to be sure to get it.

                  1 Reply Last reply
                  0
                  • T Offline
                    T Offline
                    TomNow99
                    wrote on last edited by
                    #9

                    @mrjj But I don't understand your idea.

                    Filter on application. Do you think about eventFilter and installEventFilter? But in application? Do you think about that variable which I create in main.cpp?

                    mrjjM 1 Reply Last reply
                    0
                    • T TomNow99

                      @mrjj But I don't understand your idea.

                      Filter on application. Do you think about eventFilter and installEventFilter? But in application? Do you think about that variable which I create in main.cpp?

                      mrjjM Offline
                      mrjjM Offline
                      mrjj
                      Lifetime Qt Champion
                      wrote on last edited by mrjj
                      #10

                      @TomNow99
                      Hi
                      Like
                      qApp->installEventFilter(filter)
                      qApp is macro to access the one from main.

                      That should allow you to see the click out side.

                      BUT

                      But Before testing that, could you test with grabMouse on dialog ?
                      it should allow you to get the final click with the code you have.

                      https://doc.qt.io/qt-5/qwidget.html#grabMouse

                      Make SURE to call releaseMouse()
                      when you close dialog. always.

                      1 Reply Last reply
                      0
                      • T Offline
                        T Offline
                        TomNow99
                        wrote on last edited by TomNow99
                        #11

                        @mrjj But what I have to add in installEventFilter function? I always add "this", but here?

                        And this grabWindow... I add this in click where I show dialog. But when I add this I can't click button to close dialog.

                        mrjjM 1 Reply Last reply
                        0
                        • T TomNow99

                          @mrjj But what I have to add in installEventFilter function? I always add "this", but here?

                          And this grabWindow... I add this in click where I show dialog. But when I add this I can't click button to close dialog.

                          mrjjM Offline
                          mrjjM Offline
                          mrjj
                          Lifetime Qt Champion
                          wrote on last edited by
                          #12

                          @TomNow99
                          hi
                          The "this" is the pointer to the QObject that has the filter func
                          see here
                          https://forum.qt.io/topic/83995/eventfilter-anywhere-in-the-program/3
                          its sets on the QApp. So I guess this for you would be where you have the filterfunction, maybe the dialog or the button.

                          Its grapmouse :) Did you read about it ?
                          What it does ?
                          If you tell dialog to grab mouse you cannot click button while dialog is open. but it will work with click outside but that click is used to close dialog and it wont go to button that is outside.

                          1 Reply Last reply
                          1
                          • T Offline
                            T Offline
                            TomNow99
                            wrote on last edited by
                            #13

                            @mrjj I understand filter. Thank you :)

                            GrabMouse - I understand fifty - fifty :D

                            True - I can't click on button. But when I click outside the button ( MainWindow, where I add button ) ) I can't close dialog. When I clicked outside app ( for example click on desktop ) I close dialog.

                            mrjjM 1 Reply Last reply
                            0
                            • T TomNow99

                              @mrjj I understand filter. Thank you :)

                              GrabMouse - I understand fifty - fifty :D

                              True - I can't click on button. But when I click outside the button ( MainWindow, where I add button ) ) I can't close dialog. When I clicked outside app ( for example click on desktop ) I close dialog.

                              mrjjM Offline
                              mrjjM Offline
                              mrjj
                              Lifetime Qt Champion
                              wrote on last edited by
                              #14

                              @TomNow99
                              Ok good :)
                              well grabmouse simply make all events go to one widget instead of the normal way where they go to widget under mouse
                              so we say "give me all"

                              Should also work clicking in MainWindow. you should also get that event.

                              1 Reply Last reply
                              0
                              • T Offline
                                T Offline
                                TomNow99
                                wrote on last edited by
                                #15

                                @mrjj Now my code looks like:

                                MainWindow ( where I have button which shows / hides dialog ):

                                #include "mainwindow.h"
                                #include "ui_mainwindow.h"
                                
                                MainWindow::MainWindow(QWidget *parent)
                                    : QMainWindow(parent)
                                    , ui(new Ui::MainWindow)
                                {
                                    ui->setupUi(this);
                                    button = new QPushButton(this);
                                    button->setGeometry(100,100,100,100);
                                    connect(button, SIGNAL(clicked()), this, SLOT(clickedSlot()));
                                    widget = new tenWidget; // tenWidget is a dialog
                                    widget->setFixedSize(300,300);
                                    widget->setFocus();
                                
                                }
                                
                                MainWindow::~MainWindow()
                                {
                                    delete ui;
                                }
                                
                                void MainWindow::clickedSlot()
                                {
                                    static int click=1;
                                
                                    if(click%2==1)
                                    {
                                        widget->show();
                                        grabMouse();
                                    }
                                    else
                                    {
                                        //widget->hide();
                                    }
                                    click++;
                                }
                                
                                

                                and the dialog ( tenWidget ):

                                #include "tenwidget.h"
                                
                                tenWidget::tenWidget(QWidget *parent)
                                {
                                    setWindowFlag( Qt::FramelessWindowHint);
                                    setStyleSheet("QDialog {background-color:red}");
                                }
                                
                                void tenWidget::focusOutEvent(QFocusEvent *event)
                                {
                                    hide();
                                    releaseMouse();
                                }
                                

                                Do you think about something like that? Or somewhere I have error?

                                mrjjM 1 Reply Last reply
                                0
                                • T TomNow99

                                  @mrjj Now my code looks like:

                                  MainWindow ( where I have button which shows / hides dialog ):

                                  #include "mainwindow.h"
                                  #include "ui_mainwindow.h"
                                  
                                  MainWindow::MainWindow(QWidget *parent)
                                      : QMainWindow(parent)
                                      , ui(new Ui::MainWindow)
                                  {
                                      ui->setupUi(this);
                                      button = new QPushButton(this);
                                      button->setGeometry(100,100,100,100);
                                      connect(button, SIGNAL(clicked()), this, SLOT(clickedSlot()));
                                      widget = new tenWidget; // tenWidget is a dialog
                                      widget->setFixedSize(300,300);
                                      widget->setFocus();
                                  
                                  }
                                  
                                  MainWindow::~MainWindow()
                                  {
                                      delete ui;
                                  }
                                  
                                  void MainWindow::clickedSlot()
                                  {
                                      static int click=1;
                                  
                                      if(click%2==1)
                                      {
                                          widget->show();
                                          grabMouse();
                                      }
                                      else
                                      {
                                          //widget->hide();
                                      }
                                      click++;
                                  }
                                  
                                  

                                  and the dialog ( tenWidget ):

                                  #include "tenwidget.h"
                                  
                                  tenWidget::tenWidget(QWidget *parent)
                                  {
                                      setWindowFlag( Qt::FramelessWindowHint);
                                      setStyleSheet("QDialog {background-color:red}");
                                  }
                                  
                                  void tenWidget::focusOutEvent(QFocusEvent *event)
                                  {
                                      hide();
                                      releaseMouse();
                                  }
                                  

                                  Do you think about something like that? Or somewhere I have error?

                                  mrjjM Offline
                                  mrjjM Offline
                                  mrjj
                                  Lifetime Qt Champion
                                  wrote on last edited by
                                  #16

                                  @TomNow99
                                  Hi
                                  I was thinking tenWidget both had grab and release mouse.
                                  As if you let button grab mouse then im not sure you can click on anything in tenWidget.

                                  So i would let it grabmouse so it can get the click out side event.
                                  then it can close it. but you cant click on button while its up but clicking over it will close anyway.
                                  its not just really the button :)

                                  1 Reply Last reply
                                  0
                                  • T Offline
                                    T Offline
                                    TomNow99
                                    wrote on last edited by TomNow99
                                    #17

                                    @mrjj I read your post the fourth time and I don't know what I should do next :D

                                    Should I change the place in the code where I grab or release mouse?

                                    EDIT:
                                    Of course I change:

                                    grabWindow();
                                    

                                    to

                                    widget->grabMouse();
                                    

                                    in mainWindow.

                                    But the effect is the same.

                                    mrjjM 1 Reply Last reply
                                    0
                                    • T TomNow99

                                      @mrjj I read your post the fourth time and I don't know what I should do next :D

                                      Should I change the place in the code where I grab or release mouse?

                                      EDIT:
                                      Of course I change:

                                      grabWindow();
                                      

                                      to

                                      widget->grabMouse();
                                      

                                      in mainWindow.

                                      But the effect is the same.

                                      mrjjM Offline
                                      mrjjM Offline
                                      mrjj
                                      Lifetime Qt Champion
                                      wrote on last edited by
                                      #18

                                      @TomNow99
                                      Hi
                                      well widget->grabMouse(); should be fine
                                      I dont see the event filter ?
                                      But you have on on the tenWidget (widget) correct ?

                                      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