Results 1 to 10 of 10

Thread: Detecting and reacting to mouse dragging in QGraphicsView?

  1. #1
    Join Date
    Oct 2009
    Posts
    23
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Detecting and reacting to mouse dragging in QGraphicsView?

    Hello, I'm trying to detect a mouse dragging across the screen but despite subclassing QGraphicsScene and over-writing dragMoveEvent(), it doesn't seem like my mouse dragging is being detected (The debug string isn't being executed). I'm not looking for drag and drop functionality, I'm just trying to customize what happens in the scene when a mouse is dragged across. Basically, I need the whole scene to shift as the mouse is dragged such that it's like the mouse is dragging the scene around with all of its images, kind of like how adobe's pdf reader can drag around the document when the mouse is dragged. I was thinking about changing the image's positions in the scene and not the scene itself.

    In implementing this, I was thinking about detecting the mouse drag event and then changing a global variable (Just for testing) that denotes the offset, and then this offset is communicated to all the Qpixmaps on the scene through the advance() function which sets the image's individual positions. The scene needs to be "scrollable" in such a way that the image needs to be freed when it goes off the screen too far, and the new images on the other side that are coming into the scene(or viewport or whatever the thing you see is called) are loaded and shown.

    I know it'd be possible to implement scrollbars and do all that funky jazz to get easy scroll functionality but scroll-bars don't make sense for my application.



    Qt Code:
    1. #include <QApplication>
    2. #include <QGraphicsEllipseItem>
    3. #include <QGraphicsScene>
    4. #include <QGraphicsView>
    5.  
    6. #include <qdatetime.h>
    7. #include <qmainwindow.h>
    8. #include <qstatusbar.h>
    9. #include <qmessagebox.h>
    10. #include <qmenubar.h>
    11. #include <qapplication.h>
    12. #include <qpainter.h>
    13. #include <qprinter.h>
    14. #include <qlabel.h>
    15. #include <qimage.h>
    16. #include <qpixmap.h>
    17. #include <QMouseEvent>
    18. #include <QStyleOptionGraphicsItem>
    19. #include <qdebug.h>
    20. #include <stdlib.h>
    21. #include <qtimer.h>
    22.  
    23. QString myImgName = "myimg.png";
    24. static QImage *myImg;
    25.  
    26.  
    27. int xOffset;
    28. int yOffset;
    29.  
    30.  
    31. static const int imageRTTI = 984376;
    32.  
    33. void debug(QString s)
    34. {
    35. qDebug(s.toAscii());
    36. }
    37.  
    38. class mapScene: public QGraphicsScene
    39. {
    40. public:
    41. mapScene();
    42.  
    43. QPoint prevMousePoint;
    44. QPoint currMousePoint;
    45. protected:
    46. void dragMoveEvent ( QGraphicsSceneDragDropEvent * event );
    47. };
    48.  
    49. mapScene::mapScene()
    50. {
    51. xOffset =0;
    52. yOffset =0;
    53. }
    54.  
    55.  
    56. void mapScene::dragMoveEvent( QGraphicsSceneDragDropEvent * event)
    57. {
    58. debug("I vus here!");
    59. xOffset = 1;
    60. yOffset = 1;
    61. }
    62.  
    63.  
    64.  
    65. class ImageItem: public QGraphicsRectItem
    66. {
    67. public:
    68. ImageItem( QImage img );
    69. int rtti () const { return imageRTTI; }
    70. void advance(int phase);
    71. protected:
    72. void paint( QPainter *, const QStyleOptionGraphicsItem *option, QWidget *widget );
    73. private:
    74. QImage image;
    75. QPixmap pixmap;
    76. int state;
    77. };
    78.  
    79.  
    80. void ImageItem::advance(int phase)
    81. {
    82. moveBy(xOffset,yOffset);
    83. }
    84.  
    85.  
    86. ImageItem::ImageItem( QImage img )
    87. : image(img)
    88. {
    89. state = 0;
    90. setRect(0, 0, image.width(), image.height());
    91. setFlag(ItemIsMovable);
    92. #if !defined(Q_WS_QWS)
    93. pixmap = pixmap.fromImage(image, Qt::OrderedAlphaDither);
    94. #endif
    95. }
    96.  
    97. void ImageItem::paint( QPainter *p, const QStyleOptionGraphicsItem *option, QWidget * )
    98. {
    99. // On Qt/Embedded, we can paint a QImage as fast as a QPixmap,
    100. // but on other platforms, we need to use a QPixmap.
    101. #if defined(Q_WS_QWS)
    102. p->drawImage( option->exposedRect, image, option->exposedRect, Qt::OrderedAlphaDither );
    103. #else
    104. p->drawPixmap( option->exposedRect, pixmap, option->exposedRect );
    105. #endif
    106. }
    107.  
    108. int main( int argc, char **argv )
    109. {
    110.  
    111. QApplication app(argc, argv);
    112.  
    113. mapScene scene;
    114. scene.setSceneRect( -100.0, -100.0, 200.0, 200.0 );
    115.  
    116. myImg = new QImage;
    117. myImg->load(myImgName);
    118.  
    119.  
    120. QAbstractGraphicsShapeItem* i = new ImageItem(*myImg);
    121. scene.addItem(i);
    122. i->setPos(-50,-50);
    123.  
    124. QTimer timer;
    125. QObject::connect(&timer, SIGNAL(timeout()), &scene, SLOT(advance()));
    126. timer.start(100);
    127.  
    128. QGraphicsView view( &scene );
    129. view.setRenderHints( QPainter::Antialiasing );
    130. view.show();
    131.  
    132. return app.exec();
    133. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Oct 2009
    Posts
    23
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Detecting and reacting to mouse dragging in QGraphicsView?

    I just realized that I meant to use MouseMoveEvent() instead of DragMoveEvent.

    However, it seems that this event doesn't really detect "dragging" (mouse click down and moving"). Maybe I have to manually manage the dragging event by using clicking, release and move events?

  3. #3
    Join Date
    Oct 2009
    Posts
    23
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Detecting and reacting to mouse dragging in QGraphicsView?

    Ok, I figured out how to detection using the MousePressEvent and MouseReleaseEvent and MouseMove event to do the "detect the mouse is dragging" part, now I need to retrieve the position of the mouse to do image-moving calculations. Does anyone have a snippet of code to do this?

    I have this code currently, but it complains.

    Qt Code:
    1. void mapScene::mouseMoveEvent( QGraphicsSceneMouseEvent * event)
    2. {
    3. debug("I vus here 2!");
    4. prevMousePoint = event->lastPos();
    5. currMousePoint = event->pos();
    6. if(mouseDown)
    7. {
    8.  
    9. // xOffset = event->pos().x() - event->lastPos().x();
    10. //yOffset = 1;
    11. }
    12. }
    To copy to clipboard, switch view to plain text mode 

    Complaint:
    error: invalid use of undefined type `struct QGraphicsSceneMouseEvent'
    error: invalid use of undefined type `struct QGraphicsSceneMouseEvent'
    And it points to the lines where prevMousePoint and currMousePoint are. Both variables are of the type QPointF.

  4. #4
    Join Date
    Oct 2009
    Posts
    23
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Detecting and reacting to mouse dragging in QGraphicsView?

    Apparently I had to...

    #include <QtGui>

    And I thought my include list was already long enough. Hopefully QtGui is the mothership of all Qt includes.

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Detecting and reacting to mouse dragging in QGraphicsView?

    Use QGraphicsView::setDragMode() with QGraphicsView::ScrollHandDrag. You don't need to do anything else, touching the scene included.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  6. The following user says thank you to wysota for this useful post:

    ajo (25th February 2013)

  7. #6
    Join Date
    Oct 2009
    Posts
    23
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Detecting and reacting to mouse dragging in QGraphicsView?

    Quote Originally Posted by wysota View Post
    Use QGraphicsView::setDragMode() with QGraphicsView::ScrollHandDrag. You don't need to do anything else, touching the scene included.
    Neat!

    I've implemented in the code, and I do get the hand cursor with it grasping when I hold down the mouse button, but the image on the screen isn't moving. Here's the code.

    Qt Code:
    1. #include <QApplication>
    2. #include <QGraphicsEllipseItem>
    3. #include <QGraphicsScene>
    4. #include <QGraphicsView>
    5. #include <QtGui>
    6.  
    7. #include <qdatetime.h>
    8. #include <qmainwindow.h>
    9. #include <qstatusbar.h>
    10. #include <qmessagebox.h>
    11. #include <qmenubar.h>
    12. #include <qapplication.h>
    13. #include <qpainter.h>
    14. #include <qprinter.h>
    15. #include <qlabel.h>
    16. #include <qimage.h>
    17. #include <qpixmap.h>
    18. #include <QMouseEvent>
    19. #include <QStyleOptionGraphicsItem>
    20. #include <qdebug.h>
    21. #include <stdlib.h>
    22. #include <qtimer.h>
    23.  
    24. QString myImgName = "myimg.png";
    25. static QImage *myImg;
    26.  
    27. int xOffset;
    28. int yOffset;
    29.  
    30. static const int imageRTTI = 984376;
    31.  
    32. void debug(QString s)
    33. {
    34. qDebug(s.toAscii());
    35. }
    36.  
    37. class ImageItem: public QGraphicsRectItem
    38. {
    39. public:
    40. ImageItem( QImage img );
    41. int rtti () const { return imageRTTI; }
    42. void advance(int phase);
    43. protected:
    44. void paint( QPainter *, const QStyleOptionGraphicsItem *option, QWidget *widget );
    45. private:
    46. QImage image;
    47. QPixmap pixmap;
    48. int state;
    49. };
    50.  
    51.  
    52. void ImageItem::advance(int phase)
    53. {
    54.  
    55. // moveBy(xOffset,yOffset);
    56. }
    57.  
    58.  
    59. ImageItem::ImageItem( QImage img )
    60. : image(img)
    61. {
    62. state = 0;
    63. setRect(0, 0, image.width(), image.height());
    64. setFlag(ItemIsMovable);
    65. #if !defined(Q_WS_QWS)
    66. pixmap = pixmap.fromImage(image, Qt::OrderedAlphaDither);
    67. #endif
    68. }
    69.  
    70. void ImageItem::paint( QPainter *p, const QStyleOptionGraphicsItem *option, QWidget * )
    71. {
    72. // On Qt/Embedded, we can paint a QImage as fast as a QPixmap,
    73. // but on other platforms, we need to use a QPixmap.
    74. #if defined(Q_WS_QWS)
    75. p->drawImage( option->exposedRect, image, option->exposedRect, Qt::OrderedAlphaDither );
    76. #else
    77. p->drawPixmap( option->exposedRect, pixmap, option->exposedRect );
    78. #endif
    79. }
    80.  
    81. int main( int argc, char **argv )
    82. {
    83.  
    84. QApplication app(argc, argv);
    85.  
    86. QGraphicsScene scene;//mapScene scene;
    87. scene.setSceneRect( -100.0, -100.0, 200.0, 200.0 );
    88.  
    89. myImg = new QImage;
    90. myImg->load(myImgName);
    91.  
    92.  
    93. QAbstractGraphicsShapeItem* i = new ImageItem(*myImg);
    94. scene.addItem(i);
    95. i->setPos(-50,-50);
    96.  
    97. QTimer timer;
    98. QObject::connect(&timer, SIGNAL(timeout()), &scene, SLOT(advance()));
    99. timer.start(100);
    100.  
    101.  
    102. QGraphicsView view( &scene );
    103. view.setDragMode(QGraphicsView::ScrollHandDrag);
    104. view.setRenderHints( QPainter::Antialiasing );
    105. view.show();
    106.  
    107. return app.exec();
    108. }
    To copy to clipboard, switch view to plain text mode 

  8. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Detecting and reacting to mouse dragging in QGraphicsView?

    Most likely your scene is smaller than your view, so there is not much to move. Make your scene larger and try again.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  9. #8
    Join Date
    Oct 2009
    Posts
    23
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Detecting and reacting to mouse dragging in QGraphicsView?

    So I made the scene larger using setRect, and indeed, it turned out to be draggable. I noticed the scroll bars, though, and the view was only draggable upto the extent of the scroll-bars. My application will potentially have billions of different images and the area that could be potentially viewed could be thought of being infinite, so I'm not sure how appropriate the scroll-bars would be and I'm not sure how well graphics-view can handle billions of qGraphics item entities, even though the image data itself would be loaded and deallocated as needed, so I'm not so worried about memory performance. More along the lines of the scene being able to think that there's tons of other graphics items out there. Would it be possible to allocate and deallocate graphics items as the view shifts around on the scene when dragging it around?

  10. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Detecting and reacting to mouse dragging in QGraphicsView?

    Quote Originally Posted by swbluto View Post
    I noticed the scroll bars, though, and the view was only draggable upto the extent of the scroll-bars.
    That's the point of this method.

    My application will potentially have billions of different images and the area that could be potentially viewed could be thought of being infinite,
    There is no such thing as infinity in computer science. You wouldn't be able to load billions of items into the scene anyway, so maybe the GraphicsView architecture is simply not for you. To me it seems you need a simple QWidget subclass capable of handling one or two images at most and loading them on the fly as the user "scrolls" through them. Then it is just a matter of handling mousePressEvent() and mouseMoveEvent() for your widget and reimplementing paintEvent() to do the drawing.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  11. #10
    Join Date
    Oct 2009
    Posts
    23
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default

    Ok, so I'm trying to do things with the MousePress, MouseRelease and MouseMove events and they all seem to work as far as they seem like they're literally supposed to work, but I use a custom boolean "mouseDown" to detect if the mouse is down and realized I need to process code whenever the mouse is down, whether moving or not. MousePress only triggers on a mouse press, MouseRelease only triggers when it's released, and MouseMove only triggers when the mouse is moved. How can I implement something that's triggered whenever the custom boolean "mouseDown" is true (or any condition is true for that matter)?

    Ok, I never did implement the "execute whenever mousedown" is true, but I found another way around the problem I was having. When I move the mouse with the button down and then stopped, the "change x" variable of the image didn't go to zero (i.e. the image kept moving), so I needed to find a way to detect when the mouse stopped moving and that's what the mouseDown boolean was for.

    However, I found that just by resetting the "change x" variable of the image to zero after advancing the image with "advance()" did what I wanted to. So no problems there.

    Now, I need to make it "unchoppy" and the image seems to "slip" in regard to the mouse moving when I move "fast". I think I need advance() to trigger whenever the mouse is moved instead of on a fixed time interval... how would I do that? I'm thinking it has something to do with slots.

    wait, would it be as simple as calling advance() inside the mouseMove event function? Can I even call advance() inside the QGraphicsScene class? *investigates*

    Woah! I just found that I could call advance() directly inside the QGraphicsScene subclass and now it's truly dragging! Here's my code just in case some other n00b might benefit from it.

    Qt Code:
    1. //#include <Q4MemArray>
    2. //#include "canvas.h"
    3. //#include <q4progressdialog.h>
    4. //#include <Q4PointArray>
    5. //#include <Q4PtrList>
    6. //#include <QPixmap>
    7. //#include "mapscene.h"
    8. //#include <Q4PopupMenu>
    9.  
    10. #include <QApplication>
    11. #include <QGraphicsEllipseItem>
    12. #include <QGraphicsScene>
    13. #include <QGraphicsView>
    14. #include <QtGui>
    15.  
    16. #include <qdatetime.h>
    17. #include <qmainwindow.h>
    18. #include <qstatusbar.h>
    19. #include <qmessagebox.h>
    20. #include <qmenubar.h>
    21. #include <qapplication.h>
    22. #include <qpainter.h>
    23. #include <qprinter.h>
    24. #include <qlabel.h>
    25. #include <qimage.h>
    26. #include <qpixmap.h>
    27. #include <QMouseEvent>
    28. #include <QStyleOptionGraphicsItem>
    29. #include <qdebug.h>
    30. #include <stdlib.h>
    31. #include <qtimer.h>
    32.  
    33.  
    34. QString myImgName = "myimg.png";
    35. static QImage *myImg;
    36.  
    37. int xOffset;
    38. int yOffset;
    39.  
    40. static const int imageRTTI = 984376;
    41.  
    42. void debug(QString s)
    43. {
    44. qDebug(s.toAscii());
    45. }
    46.  
    47. class mapScene: public QGraphicsScene
    48. {
    49. public:
    50. mapScene();
    51.  
    52. int mouseMoveX;
    53. int mouseMoveY;
    54. QPointF prevMousePoint;
    55. QPointF currMousePoint;
    56.  
    57. bool mouseDown;
    58. protected:
    59. void mouseMoveEvent ( QGraphicsSceneMouseEvent * mouseEvent );
    60. void mousePressEvent ( QGraphicsSceneMouseEvent * mouseEvent );
    61. void mouseReleaseEvent ( QGraphicsSceneMouseEvent * mouseEvent );
    62.  
    63. };
    64.  
    65. mapScene::mapScene()
    66. {
    67. mouseDown = false;
    68. mouseMoveX = 0;
    69. mouseMoveY = 0;
    70. xOffset =0;
    71. yOffset =0;
    72.  
    73. }
    74.  
    75. void mapScene::mouseMoveEvent( QGraphicsSceneMouseEvent * event)
    76. {
    77. if(mouseDown)
    78. {
    79. QString dummy;
    80. debug("mommy");
    81. /*
    82.   debug(dummy.setNum(event->pos().x()));
    83.   debug(dummy.setNum(event->lastPos().x()));
    84.   debug(dummy.setNum(event->lastScenePos().x()));
    85.   debug(dummy.setNum(event->scenePos().x()));
    86.   */
    87. xOffset = (int)(event->scenePos().x() - event->lastScenePos().x());
    88. yOffset = (int)(event->scenePos().y() - event->lastScenePos().y());
    89. advance();
    90. }
    91. else
    92. {
    93. xOffset = 0;
    94. yOffset = 0;
    95. }
    96. }
    97.  
    98. void mapScene::mousePressEvent( QGraphicsSceneMouseEvent * event)
    99. {
    100. mouseDown = true;
    101. }
    102.  
    103. void mapScene::mouseReleaseEvent( QGraphicsSceneMouseEvent * event)
    104. {
    105. mouseDown = false;
    106. xOffset = 0;
    107. yOffset = 0;
    108. }
    109.  
    110.  
    111.  
    112. class ImageItem: public QGraphicsRectItem
    113. {
    114. public:
    115. ImageItem( QImage img );
    116. int rtti () const { return imageRTTI; }
    117. void advance(int phase);
    118. protected:
    119. void paint( QPainter *, const QStyleOptionGraphicsItem *option, QWidget *widget );
    120. private:
    121. QImage image;
    122. QPixmap pixmap;
    123. int state;
    124. };
    125.  
    126.  
    127. void ImageItem::advance(int phase)
    128. {
    129.  
    130. moveBy(xOffset,yOffset);
    131. xOffset = 0; yOffset = 0;
    132. }
    133.  
    134.  
    135. ImageItem::ImageItem( QImage img )
    136. : image(img)
    137. {
    138. state = 0;
    139. setRect(0, 0, image.width(), image.height());
    140. setFlag(ItemIsMovable);
    141. #if !defined(Q_WS_QWS)
    142. pixmap = pixmap.fromImage(image, Qt::OrderedAlphaDither);
    143. #endif
    144. }
    145.  
    146. void ImageItem::paint( QPainter *p, const QStyleOptionGraphicsItem *option, QWidget * )
    147. {
    148. // On Qt/Embedded, we can paint a QImage as fast as a QPixmap,
    149. // but on other platforms, we need to use a QPixmap.
    150. #if defined(Q_WS_QWS)
    151. p->drawImage( option->exposedRect, image, option->exposedRect, Qt::OrderedAlphaDither );
    152. #else
    153. p->drawPixmap( option->exposedRect, pixmap, option->exposedRect );
    154. #endif
    155. }
    156.  
    157. int main( int argc, char **argv )
    158. {
    159.  
    160. QApplication app(argc, argv);
    161.  
    162. mapScene scene;//mapScene scene;
    163. scene.setSceneRect( -500.0, -500.0, 1000.0, 1000.0 );//( -100.0, -100.0, 200.0, 200.0 );
    164.  
    165. myImg = new QImage;
    166. myImg->load(myImgName);
    167.  
    168.  
    169. QAbstractGraphicsShapeItem* i = new ImageItem(*myImg);
    170. scene.addItem(i);
    171. i->setPos(-50,-50);
    172.  
    173.  
    174.  
    175. QGraphicsView view( &scene );
    176. // view.setDragMode(QGraphicsView::ScrollHandDrag);
    177. view.setRenderHints( QPainter::Antialiasing );
    178. view.show();
    179.  
    180. return app.exec();
    181. }
    To copy to clipboard, switch view to plain text mode 

    I'm now trying to get this dragging behavior to work for multiple images all at the same time but only one image (coindentally, the first one that I added to the scene) moves, but if the first one goes off the screen, then the second one moves, albeit at a slower rate than the mouse moving meaning it's only getting triggered to move a part of the time the mouse is moved. It seems this is sufficiently different to deserve its own thread, so I'm posting that issue at http://www.qtcentre.org/forum/f-qt-p...ene-25083.html .
    Last edited by wysota; 26th October 2009 at 09:24. Reason: If you are replying to your own posts, please edit the original post instead

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.