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.
Code:
#include <QApplication>
#include <QGraphicsEllipseItem>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <qdatetime.h>
#include <qmainwindow.h>
#include <qstatusbar.h>
#include <qmessagebox.h>
#include <qmenubar.h>
#include <qapplication.h>
#include <qpainter.h>
#include <qprinter.h>
#include <qlabel.h>
#include <qimage.h>
#include <qpixmap.h>
#include <QMouseEvent>
#include <QStyleOptionGraphicsItem>
#include <qdebug.h>
#include <stdlib.h>
#include <qtimer.h>
int xOffset;
int yOffset;
static const int imageRTTI = 984376;
{
qDebug(s.toAscii());
}
{
public:
mapScene();
protected:
void dragMoveEvent ( QGraphicsSceneDragDropEvent * event );
};
mapScene::mapScene()
{
xOffset =0;
yOffset =0;
}
void mapScene::dragMoveEvent( QGraphicsSceneDragDropEvent * event)
{
debug("I vus here!");
xOffset = 1;
yOffset = 1;
}
{
public:
int rtti () const { return imageRTTI; }
void advance(int phase);
protected:
private:
int state;
};
void ImageItem::advance(int phase)
{
moveBy(xOffset,yOffset);
}
ImageItem
::ImageItem( QImage img
) : image(img)
{
state = 0;
setRect(0, 0, image.width(), image.height());
setFlag(ItemIsMovable);
#if !defined(Q_WS_QWS)
pixmap = pixmap.fromImage(image, Qt::OrderedAlphaDither);
#endif
}
{
// On Qt/Embedded, we can paint a QImage as fast as a QPixmap,
// but on other platforms, we need to use a QPixmap.
#if defined(Q_WS_QWS)
p->drawImage( option->exposedRect, image, option->exposedRect, Qt::OrderedAlphaDither );
#else
p->drawPixmap( option->exposedRect, pixmap, option->exposedRect );
#endif
}
int main( int argc, char **argv )
{
mapScene scene;
scene.setSceneRect( -100.0, -100.0, 200.0, 200.0 );
myImg->load(myImgName);
scene.addItem(i);
i->setPos(-50,-50);
QObject::connect(&timer,
SIGNAL(timeout
()),
&scene,
SLOT(advance
()));
timer.start(100);
view.
setRenderHints( QPainter::Antialiasing );
view.show();
return app.exec();
}
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?
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.
Code:
{
debug("I vus here 2!");
prevMousePoint = event->lastPos();
currMousePoint = event->pos();
if(mouseDown)
{
// xOffset = event->pos().x() - event->lastPos().x();
//yOffset = 1;
}
}
Complaint:
Quote:
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.
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.
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.
Re: Detecting and reacting to mouse dragging in QGraphicsView?
Quote:
Originally Posted by
wysota
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.
Code:
#include <QApplication>
#include <QGraphicsEllipseItem>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QtGui>
#include <qdatetime.h>
#include <qmainwindow.h>
#include <qstatusbar.h>
#include <qmessagebox.h>
#include <qmenubar.h>
#include <qapplication.h>
#include <qpainter.h>
#include <qprinter.h>
#include <qlabel.h>
#include <qimage.h>
#include <qpixmap.h>
#include <QMouseEvent>
#include <QStyleOptionGraphicsItem>
#include <qdebug.h>
#include <stdlib.h>
#include <qtimer.h>
int xOffset;
int yOffset;
static const int imageRTTI = 984376;
{
qDebug(s.toAscii());
}
{
public:
int rtti () const { return imageRTTI; }
void advance(int phase);
protected:
private:
int state;
};
void ImageItem::advance(int phase)
{
// moveBy(xOffset,yOffset);
}
ImageItem
::ImageItem( QImage img
) : image(img)
{
state = 0;
setRect(0, 0, image.width(), image.height());
setFlag(ItemIsMovable);
#if !defined(Q_WS_QWS)
pixmap = pixmap.fromImage(image, Qt::OrderedAlphaDither);
#endif
}
{
// On Qt/Embedded, we can paint a QImage as fast as a QPixmap,
// but on other platforms, we need to use a QPixmap.
#if defined(Q_WS_QWS)
p->drawImage( option->exposedRect, image, option->exposedRect, Qt::OrderedAlphaDither );
#else
p->drawPixmap( option->exposedRect, pixmap, option->exposedRect );
#endif
}
int main( int argc, char **argv )
{
scene.setSceneRect( -100.0, -100.0, 200.0, 200.0 );
myImg->load(myImgName);
scene.addItem(i);
i->setPos(-50,-50);
QObject::connect(&timer,
SIGNAL(timeout
()),
&scene,
SLOT(advance
()));
timer.start(100);
view.
setRenderHints( QPainter::Antialiasing );
view.show();
return app.exec();
}
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.
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?
Re: Detecting and reacting to mouse dragging in QGraphicsView?
Quote:
Originally Posted by
swbluto
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.
Quote:
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.