Results 1 to 5 of 5

Thread: Receiving events while mouse is pressed

  1. #1
    Join Date
    May 2014
    Posts
    3
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Receiving events while mouse is pressed

    Hi,

    Qt Code:
    1. QMenu menu;
    2.  
    3. menu.addAction("Item 1");
    4. menu.addAction("Item 2");
    5. menu.addAction("Item 3");
    6.  
    7. qApp->setStyleSheet("QMenu::item:selected { background: rgba(0, 0, 128, 20%); }");
    To copy to clipboard, switch view to plain text mode 
    This example creates a simple QMenu where the backgrounds of the single items get colored when the mouse is hovering over them. This also works if the mouse is pressed on "Item 1" and then hovered over the other ones (not releasing the mouse button).


    Is there a way to achieve this behaviour on widgets in a layout?
    Qt Code:
    1. QVBoxLayout layout;
    2.  
    3. layout.addWidget(new QLabel("Item 1"));
    4. layout.addWidget(new QLabel("Item 2"));
    5. layout.addWidget(new QLabel("Item 3"));
    6.  
    7. qApp->setStyleSheet("QLabel:hover { background: rgba(0, 0, 128, 20%); }");
    To copy to clipboard, switch view to plain text mode 
    With this example, the labels only get colored when the mouse is hovering them without a mouse button being pressed. If I press and hold the left mouse button on "Item 1" on hover over the other items, "Item 1" remains being colored. The others will not get colored.

    I guess this is a problem of event propagation. When the mouse is pressed and moved, only "Item 1" receives events (QEvent::MouseMove and QEvent::HoverMove). The others are not receiving any type of event.

    So is there a way to solve this problem, i.e. to let the other items also receive the events? Or if it is not a problem of event propagation, how do I achieve the same behaviour like on the QMenu?


    Thanks in advance for your help.

  2. #2
    Join Date
    Apr 2012
    Location
    India.
    Posts
    88
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Receiving events while mouse is pressed

    Read QMouseEvent class documentation, It says ....

    "Qt automatically grabs the mouse when a mouse button is pressed inside a widget; the widget will continue to receive mouse events until the last mouse button is released."

    So think about it and you should try setting "mouseTracking" false when mouse button is pressed, see if it works for you.

  3. #3
    Join Date
    May 2014
    Posts
    3
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Receiving events while mouse is pressed

    Unfortunately this does not help. Mouse tracking is set to false. I also checked whether it is set to true from Qt, but this is not the case. A QDebug output during the mouseMoveEvent does also show that the tracking is set to false.
    So tracking is not the problem.

    "Qt automatically grabs the mouse when a mouse button is pressed inside a widget; the widget will continue to receive mouse events until the last mouse button is released."

    Is there a way to disable this on specific widgets?
    I think there has to be a way, because it works on QMenu-items (see the first example that I posted). Or is it a feature that is only possible on QActions?

    Does someone know where this grabbing of the mouse is done inside the Qt-sources? I did not find it.


    Added after 28 minutes:


    What I am trying to achieve is that a QWidgetAction, that is added to a QMenu, does behave like a QAction (regarding the hovering and coloring).
    Last edited by davj; 20th May 2014 at 15:06.

  4. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Receiving events while mouse is pressed

    QMenu is a simple QWidget, the items within it are not separate sub-widgets, they're just rectangles of space within the QMenu. So there is no moving of the mouse from one widget to another within the menu, it's all within the same widget. The highlighting and all that is just internal to the implementation of QMenu painting. So the behavior of the mouse within the QMenu is exactly as the Qt documentation says, it "grabs the mouse when a mouse button is pressed within a widget".

    You might be able to work around this by implementing an event filter in the widget that contains the buttons, and installing that filter on each of the buttons you want to highlight. Turn on mouse tracking and in the event filter keep track of when the mouse leaves and enters the buttons. This is likely the same mechanism that Qt uses to distinguish between a press and release within a button (a "click") and a press on a button and release outside it (a canceled click).

    Of course, if you implement this, you'll be sending all the wrong UI clues to the user. Pressing the mouse on one button, moving to another, then releasing the mouse on a different button should not result in the same behavior as an actual click on the second button. No other GUI around has that behavior. Menus are different - people understand this - when you press the mouse on a top level item then move down the list, they know that whatever item they release it on is the one that will be executed. If you want to cancel a menu action, you move off the menu. Same thing with buttons. If you accidentally move off one button and release the mouse over another, a user never expects that to behave the same way as a click on the second button.
    Last edited by d_stranz; 21st May 2014 at 03:55.

  5. #5
    Join Date
    May 2014
    Posts
    3
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Receiving events while mouse is pressed

    Quote Originally Posted by d_stranz View Post
    Of course, if you implement this, you'll be sending all the wrong UI clues to the user. Pressing the mouse on one button, moving to another, then releasing the mouse on a different button should not result in the same behavior as an actual click on the second button. No other GUI around has that behavior. Menus are different - people understand this - when you press the mouse on a top level item then move down the list, they know that whatever item they release it on is the one that will be executed. If you want to cancel a menu action, you move off the menu. Same thing with buttons. If you accidentally move off one button and release the mouse over another, a user never expects that to behave the same way as a click on the second button.
    I have to contradict here. A QMenu does behave differently. You do not have to press and hold the mouse button on a top level item.
    Qt Code:
    1. QMenu menu;
    2.  
    3. menu.addAction("Item 1", this, SLOT(action1()));
    4. menu.addAction("Item 2", this, SLOT(action2()));
    5. menu.addAction("Item 3", this, SLOT(action3()));
    6.  
    7. qApp->setStyleSheet("QMenu::item:selected { background: rgba(0, 0, 128, 20%); }");
    To copy to clipboard, switch view to plain text mode 
    If this QMenu is open and you press the mouse button on "Item 1", move the mouse over to "Item 3" and release it there, "action3()" will be executed. There is no need to hold the button down on the top level item. You can simply open the menu, release the button that opened it, then press and hold the button on any item in the menu and release it over another. The QAction on which the button was released will be executed.
    The background coloring is done through Qt like expected, i.e. the item over which the mouse resides is colored, regardless whether the mouse button is pressed and hold or not.

    This is the default behaviour in many GUIs and Qt also does it.

    To return to my question: Implement it like this
    Qt Code:
    1. QWidgetAction * action1 = new QWidgetAction(this);
    2. QWidgetAction * action2 = new QWidgetAction(this);
    3. QWidgetAction * action3 = new QWidgetAction(this);
    4.  
    5. action1->setDefaultWidget(new QLabel("Item 1"));
    6. action2->setDefaultWidget(new QLabel("Item 2"));
    7. action3->setDefaultWidget(new QLabel("Item 3"));
    8.  
    9. QMenu menu;
    10.  
    11. menu.addAction(action1);
    12. menu.addAction(action2);
    13. menu.addAction(action3);
    14.  
    15. qApp->setStyleSheet("QMenu::item:selected, *:hover { background: rgba(0, 0, 128, 20%); }");
    To copy to clipboard, switch view to plain text mode 
    The click behaviour remains the same, i.e. press and hold the mouse on "Item 1", move it over to "Item 3" and release it there, results in "action3" being executed.
    BUT the background coloring behaves differently. In this case, the background of "Item 1" remains colored regardless where the mouse cursor resides.

    So the user gets the visual feedback of "Item 1" being colored even if the mouse cursor is over "Item 3", but if he releases the mouse button over "Item 3" "action3" gets executed.

    I suspect, that this is a problem of mouse grabbing and event propagation, but am not sure.

    The question is, how can I give the user the same visual feedback when using QWidgetActions?
    Last edited by davj; 21st May 2014 at 08:16.

Similar Threads

  1. How to detect hover events when mouse button is pressed
    By yagabey in forum Qt Programming
    Replies: 12
    Last Post: 26th April 2016, 09:23
  2. Replies: 0
    Last Post: 3rd May 2013, 16:53
  3. Replies: 5
    Last Post: 10th August 2010, 04:39
  4. how to do this ,mouse pressed,then can move the window
    By tsuibin in forum Qt Programming
    Replies: 2
    Last Post: 2nd April 2009, 19:04
  5. Problem with receiving events from QDateEdit
    By gunhelstr in forum Qt Programming
    Replies: 4
    Last Post: 20th April 2006, 11:21

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.