Detect end of movement of QMainWindow / QDialog (Qt 4.8)



  • Hi all,

    I'm using Qt 4.8.3 on X11.

    I need to know when the user ends with dragging a window around the screen,
    this in order to read the final position and eventually start an animation to adjust the window position to an "allowed" one.

    I noticed that the QWidget::moveEvent is called for each small movement, but this is very unconvenient because I must perform position checking (and eventually strat the animation) only when the user releases the mouse button and the movement is completely finished.

    This is the real problem: it seems that there is no way to detect the mouse release event (or to get the mouse buttons status) when the user clicks on the titlebar, since it is controlled by the OS and not by Qt.
    I tried also with the QWidget::x11event(XEvent* e)... but the events are collected only inside the window, not the title bar, as well.

    Does someone know a way to achieve this?

    I suspect that I will have to reimplement the titlebar myself... too bad...

    thank you! ;-)



  • Please differentiate:
    Qt = Qt framework
    QT = QuickTime



  • You can check the position in the enterEvent because to move the window the mouse has to leave the widget.



  • [quote author="napajejenunedk0" date="1350558332"]Please differentiate:
    Qt = Qt framework
    QT = QuickTime[/quote]

    Edited



  • [quote author="butterface" date="1350559970"]You can check the position in the enterEvent because to move the window the mouse has to leave the widget.[/quote]

    This implies that the user moves the mouse in the window immediately after the movement,
    this is not always true



  • Just an ideea ... in QWidget::moveEvent fire a timer with 0 ms, which

    bq. will time out as soon as all the events in the window system's event queue have been processed

    In timer event check QApplication::mouseButtons. If Qt::NoButton means widget movement has stopped.



  • Okay, thats true.
    Then you can start and restart a time and after a certain time of no movement you can move the window yourself. Of course if the user just hold the mouse still you would move the window away from the cursor. To overcome this problem you might be able to get the mouse release from your underlaying window system (X in this case).



  • [quote author="cincirin" date="1350561891"]

    will time out as soon as all the events in the window system's event queue have been processed

    [/quote]

    How can I check that all the events in the window system's event queue have been processed?
    thank you



  • [quote author="butterface" date="1350562085"]
    To overcome this problem you might be able to get the mouse release from your underlaying window system (X in this case).[/quote]

    Thanks for your answer, I tried to catch system events using QWidget::x11event, but even with this method no events that have been originated in the titlebar are catched.



  • [quote author="teomurgi" date="1350562261"]
    How can I check that all the events in the window system's event queue have been processed?
    thank you[/quote]

    You'll be informed in 0 ms timer event. See "QTimer description":http://qt-project.org/doc/qt-4.8/QTimer.html#details

    bq. As a special case, a QTimer with a timeout of 0 will time out as soon as all the events in the window system's event queue have been processed



  • I dont think you can do that within Qt. You will have to hook on your x window system directly.



  • I finally made it with the timer, not the smoothest solution in this world, but it works.
    In this example I have to reposition the widget if it lays across multiple screens at the end of the movement.

    @

    #include "STMultiScreenMovementManager.h"
    #include <QDesktopWidget>

    /**

    • Constructor.
    • @param parent: Widget under control.
      /
      STMultiScreenMovementManager::STMultiScreenMovementManager(QWidget
      parent)
      : QObject()
      {
      this->parent = parent;
      timer = new QTimer(this);
      QObject::connect(timer, SIGNAL(timeout()),this,SLOT(adjustPosition()));
      }

    STMultiScreenMovementManager::~STMultiScreenMovementManager()
    {
    DELETE_P(timer)
    }

    /**

    • Called by the moveEvent in the parent widget.
      */
      void STMultiScreenMovementManager::notifyMovement(){

    if(!timer->isActive() &&
    intersectsScreenBounds()){
    timer->start(100);
    }
    }

    /**

    • Called upon timeout: it adjusts the widget position if the current one is not permitted.
      /
      void STMultiScreenMovementManager::adjustPosition(){
      QDesktopWidget
      dw = QApplication::desktop();
      QPoint endingPos = calculateEndingPosition();
      if(parent->pos() == endingPos ||
      dw->screenGeometry(parent).contains(parent->frameGeometry())){
      timer->stop();
      }else{
      parent->move(endingPos);
      }
      }

    /**

    • This method calculates the nearest right position for the widget.
      */
      QPoint STMultiScreenMovementManager::calculateEndingPosition(){
      [........]
      return endingPos;
      }

    /**

    • This is used to find out if the widget is laying across multiple screens.
      */
      bool STMultiScreenMovementManager::intersectsScreenBounds(){
      [......]
      return true/false
      }

    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.