I have a QGraphicsView
which contains many QGraphicsItem
. If I click mouse right click on any QGraphicsItem
, the item should get select and right menu options should appear and then I will choose one of the options among them.To do that I have installed eventFilter
and through it, I am using ContextMenu
to create right click menu. Right click menu are getting cretaed properly. But propblem is I am not getting how to connect them to some function so that I can write logic for it.
It means if I clicked on save
option that particular QGraphicsItem
should get select and I should be able to go to some function where I will write logic for saving.
bool myClass::eventFilter(QObject *watched, QEvent *event)
{
switch(event->type())
{
case QEvent::ContextMenu:
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*> (event);
menu = new QMenu(this);
option = menu->addMenu("CopyOption");
option->addAction("save");
menu->exec(mouseEvent->globalPos());
break;
}
default:
break;
}
}
CodePudding user response:
In your approach you show a context menu when you have no information if any item is selected. It is rather bad idea. You don't want to show the context menu in any location of view. You have to check if a cursor mouse is over an item.
Why not to derive from QGraphicsItem
and just overload mousePressEvent
method. Inside this method check if right button of mouse is clicked. If so, show context menu and test which action is clicked. Minimal code would be:
class TItem : public QGraphicsItem
{
bool _selected = false;
public:
TItem(QGraphicsItem* parent = nullptr) : QGraphicsItem(parent) {}
QRectF boundingRect() const override { return QRectF(0,0,20,20); }
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override {
painter->fillRect(QRectF(0,0,20,20),_selected ? QColor(0,255,255) : QColor(255,255,0));
}
void mousePressEvent(QGraphicsSceneMouseEvent* e) override {
QGraphicsItem::mousePressEvent(e);
if (e->button() & Qt::RightButton) {
QMenu menu;
QAction* a1 = menu.addAction(QString("test1"));
QAction* a2 = menu.addAction(QString("test2"));
if(a2 == menu.exec(e->screenPos())) {
test2();
_selected = true;
update();
}
}
}
void test2() {
QMessageBox::information(nullptr,"test2","test2");
}
};
All the job with checking is an item is under mouse is done by QT, mousePressEvent
is invoked only if it is necessary.
Another approach would be override mousePressEvent
on QGraphicsView. Inside which:
- get all items belonging to the scene
- iterate over them, checking if an item is under mouse ->
QGraphicsItem
hasisUnderMouse
method - if any item is under mouse, create
QMenu
and show it - check selected
QAction
, if it issave
call a proper method which doing the save and mark the item as selected