I am having an issue with QGraphicsView wrt setting the cursor when working with a QGraphicsItem. The basic setup is this, I set an initial cursor (CrossCursor=2) for the viewport of the view. I use a contextMenu (thru customContextMenuRequested) to allow a selection ("Extract Item") for creating an extraction qgraphicsitem that i can move around. When this item is created I change the viewport cursor to another cursor (ForbiddenCursor=14) and I set a specific cursor (SizeAllCursor=9) for the item. I also clear the contextMenu for the view and create a signal/slot mechanism to use a contextMenu for the item. The item contextmenu just has a "DONE" option that is suppose to delete the item and set the viewport cursor back to CrossCursor. However, the cursor viewed in the viewport after the item is deleted is still the ForbiddenCursor.
I added an implementation of the viewportEvent method for the view and added a debug message for CursorChange. I see all the expected cursor changes, but there is an extra change event at the very end after I try to set the cursor back to CrossCursor. The event shows that the cursor is being set to the ForbiddenCursor.
Digging thru the Qt source code (qgraphicsview.cpp), there is an internal originalCursor that is being saved/used when a mouse move is triggered. This is where the cursor is being set back to the ForbidenCursor in the app (followed it thru with qtcreator debugger). It seems that my item contextMenu and subsequent set cursor is not seen by the qgraphicsview and the next move of the mouse sets the cursor to this original cursor, which is really an old cursor. There is no access to this originalCursor to clear it or disable its use.
I was hoping that someone can help me find a way around this issue. I need to change the cursors of the viewport with certain modes, but I cannot find the proper way/order that allows the viewport cursor to go back to the original cursor after the items use.
-----------------------
I have a much larger application that I am seeing the issue, but I have created a small app that exhibits the same behavior as descibed above and is included below.
#include <QApplication>
#include "window.h"
int main(int argc, char *argv[])
{
Window w;
w.show();
return app.exec();
}
#include <QApplication>
#include "window.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Window w;
w.show();
return app.exec();
}
To copy to clipboard, switch view to plain text mode
#ifndef _WINDOW_H_
#define _WINDOW_H_
#include <QMainWindow>
class View;
{
Q_OBJECT
public:
~Window();
public slots:
void viewContextMenu
( const QPoint & pt
);
void extractContextMenu
( const QPoint & pt,
const QRectF & rect
);
private:
View * m_view;
};
#endif
#ifndef _WINDOW_H_
#define _WINDOW_H_
#include <QMainWindow>
class QGraphicsScene;
class View;
class Window : public QMainWindow
{
Q_OBJECT
public:
Window( QWidget * p = 0 );
~Window();
public slots:
void viewContextMenu( const QPoint & pt );
void extractContextMenu( const QPoint & pt, const QRectF & rect );
private:
QGraphicsScene * m_scene;
View * m_view;
};
#endif
To copy to clipboard, switch view to plain text mode
#include "window.h"
#include "view.h"
#include "item.h"
#include <QAction>
#include <QGraphicsScene>
#include <QMenu>
{
m_scene
->setBackgroundBrush
(QBrush(Qt
::black, Qt
::SolidPattern));
m_view = new View;
m_view->setScene(m_scene);
m_view->fitInView( m_scene->sceneRect() );
setCentralWidget(m_view);
r
->setPen
( QPen(Qt
::cyan) );
r->setRect( m_scene->sceneRect() );
m_scene->addItem( r );
m_view->setContextMenuPolicy( Qt::CustomContextMenu );
connect( m_view,
SIGNAL( customContextMenuRequested
(const QPoint &) ),
SLOT( viewContextMenu
(const QPoint &) ) );
m_view->viewport()->setCursor( Qt::CrossCursor );
}
Window::~Window()
{
}
void Window
::viewContextMenu( const QPoint & pt
) {
contextMenu.addAction( tr("Extract Item") );
act = contextMenu.exec( m_view->viewport()->mapToGlobal(pt) );
if( NULL != act )
{
Item *item = new Item;
item
->setRect
( QRectF( 0,
0,
100,
100 ) );
item
->setPen
( QPen(Qt
::green) );
item
->setBrush
( QBrush(Qt
::red) );
item->setPos( m_view->mapToScene(pt) );
item->setCursor( Qt::SizeAllCursor );
connect( item,
SIGNAL( requestContextMenu(const QPoint&,const QRectF&) ),
SLOT( extractContextMenu(const QPoint&,const QRectF&) ) );
m_scene->addItem(item);
m_view->setContextMenuPolicy( Qt::DefaultContextMenu );
m_view->viewport()->setCursor( Qt::ForbiddenCursor );
}
}
void Window
::extractContextMenu( const QPoint & pt,
const QRectF & /*rect*/ ) {
Item *pGI = qobject_cast<Item*>(sender());
contextMenu.addAction( tr("Done") );
act = contextMenu.exec( pt );
if( NULL != act )
{
m_view->setContextMenuPolicy( Qt::CustomContextMenu );
m_view->scene()->removeItem( pGI );
delete pGI;
m_view->viewport()->setCursor( Qt::CrossCursor );
}
}
#include "window.h"
#include "view.h"
#include "item.h"
#include <QAction>
#include <QGraphicsScene>
#include <QMenu>
Window::Window( QWidget * p )
: QMainWindow( p )
{
m_scene = new QGraphicsScene( 0, 0, 1000, 1000);
m_scene->setBackgroundBrush(QBrush(Qt::black, Qt::SolidPattern));
m_view = new View;
m_view->setScene(m_scene);
m_view->fitInView( m_scene->sceneRect() );
setCentralWidget(m_view);
QGraphicsRectItem * r = new QGraphicsRectItem;
r->setPen( QPen(Qt::cyan) );
r->setRect( m_scene->sceneRect() );
m_scene->addItem( r );
m_view->setContextMenuPolicy( Qt::CustomContextMenu );
connect( m_view,
SIGNAL( customContextMenuRequested(const QPoint &) ),
SLOT( viewContextMenu(const QPoint &) ) );
m_view->viewport()->setCursor( Qt::CrossCursor );
}
Window::~Window()
{
}
void Window::viewContextMenu( const QPoint & pt )
{
QMenu contextMenu;
QAction * act;
contextMenu.addAction( tr("Extract Item") );
act = contextMenu.exec( m_view->viewport()->mapToGlobal(pt) );
if( NULL != act )
{
Item *item = new Item;
item->setRect( QRectF( 0, 0, 100, 100 ) );
item->setPen( QPen(Qt::green) );
item->setBrush( QBrush(Qt::red) );
item->setPos( m_view->mapToScene(pt) );
item->setCursor( Qt::SizeAllCursor );
item->setFlag( QGraphicsItem::ItemIsMovable, true );
connect( item,
SIGNAL( requestContextMenu(const QPoint&,const QRectF&) ),
SLOT( extractContextMenu(const QPoint&,const QRectF&) ) );
m_scene->addItem(item);
m_view->setContextMenuPolicy( Qt::DefaultContextMenu );
m_view->viewport()->setCursor( Qt::ForbiddenCursor );
}
}
void Window::extractContextMenu( const QPoint & pt, const QRectF & /*rect*/ )
{
QMenu contextMenu;
QAction * act;
Item *pGI = qobject_cast<Item*>(sender());
contextMenu.addAction( tr("Done") );
act = contextMenu.exec( pt );
if( NULL != act )
{
m_view->setContextMenuPolicy( Qt::CustomContextMenu );
m_view->scene()->removeItem( pGI );
delete pGI;
m_view->viewport()->setCursor( Qt::CrossCursor );
}
}
To copy to clipboard, switch view to plain text mode
#ifndef __VIEW_H__
#define __VIEW_H__
#include <QDebug>
#include <QEvent>
#include <QGraphicsView>
{
Q_OBJECT
public:
{
setFrameStyle
( QFrame::NoFrame );
setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
}
protected:
bool viewportEvent
( QEvent * event
) {
if( QEvent::CursorChange == event
->type
() ) {
qDebug() << "Cursor Change: " << viewport()->cursor().shape();
}
}
};
#endif
#ifndef __VIEW_H__
#define __VIEW_H__
#include <QDebug>
#include <QEvent>
#include <QGraphicsView>
class View : public QGraphicsView
{
Q_OBJECT
public:
View( QWidget* parent = 0 ) : QGraphicsView( parent )
{
setFrameStyle( QFrame::NoFrame );
setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
}
protected:
bool viewportEvent( QEvent * event )
{
if( QEvent::CursorChange == event->type() )
{
qDebug() << "Cursor Change: " << viewport()->cursor().shape();
}
return QGraphicsView::viewportEvent(event);
}
};
#endif
To copy to clipboard, switch view to plain text mode
#ifndef __ITEM_H__
#define __ITEM_H__
#include <QGraphicsRectItem>
#include <QGraphicsSceneMouseEvent>
{
Q_OBJECT
public:
~Item() {}
signals:
void requestContextMenu
( const QPoint & pt,
const QRectF & requestRect
);
protected:
{
emit requestContextMenu( gscme->screenPos(), mapRectToScene( rect() ) );
}
};
#endif
#ifndef __ITEM_H__
#define __ITEM_H__
#include <QGraphicsRectItem>
#include <QGraphicsSceneMouseEvent>
class Item : public QObject, public QGraphicsRectItem
{
Q_OBJECT
public:
Item() : QGraphicsRectItem( NULL ) {}
~Item() {}
signals:
void requestContextMenu( const QPoint & pt, const QRectF & requestRect );
protected:
void contextMenuEvent( QGraphicsSceneContextMenuEvent* gscme )
{
emit requestContextMenu( gscme->screenPos(), mapRectToScene( rect() ) );
}
};
#endif
To copy to clipboard, switch view to plain text mode
Bookmarks