The function QGraphicsScene::itemAt problem
-
Hi all,
I've created a custom class (named as Flow) inherited by QGraphicsItem. It's composing of an arrow and curve. I've used the function itemAt to determine which item has selected when QGraphicsScene::mousePressEvent is called. But it does not always return correct item. Otherwise I've written the folllowing function for manual detection. It's working correctly. But I want to learn why sometimes QGraphicsScene can not detect item selected by pressing mouse? Is there a more sensible method than manual point control?
@
int getMatchedFlow(QPointF pos)
{
int fID = -1;
QList<Flow*> mFlowList = mGroupStore.keys();
QList<Flow*>::iterator i;
Flow *pFlow;for (i = mFlowList.begin(); i != mFlowList.end(); ++i) { pFlow = (Flow*)*i; if (pFlow->checkPointSet(pos)) { fID = pFlow->getID(); break; } } return fID;
}
bool Flow::checkPointSet(QPointF point)
{
bool rc = false;if (mBoundingPath.contains(point)) { rc = true; } return rc;
}
@Thanks a lot for your helps,
-
Hi,
Too bad that you didn't share the code that is not working...
I think you're doing this really wrong and may have some serious trouble in future with your approach, however few good solutions that you may use:
There are much better ways to determine the selected item...
If you don't want to use the QGraphicsObject, allow your items to be really selected by setFlag(QGraphicsItem::ItemIsSelectable, true), now in event, iterate over items and check it by isSelected()
Use QGraphicsObject Instead of QGraphicsItem, reimplement the mousePressEvent, put the emit some singal inside and catch the signal.
Look at some sample code that I wrote for you (It's not about the code quality, I just want to give you an idea):
header:
@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QtGui>
class TextItem : public QGraphicsTextItem
{
Q_OBJECT
public:
TextItem( const QString & text, QGraphicsItem * parent = 0 )
: QGraphicsTextItem( text, parent )
{
//Optional
//setFlag(QGraphicsItem::ItemIsMovable, true);
//setFlag(QGraphicsItem::ItemIsSelectable, true);
}void mousePressEvent( QGraphicsSceneMouseEvent *e ) { qDebug() << __PRETTY_FUNCTION__; emit itemClicked(); QGraphicsTextItem::mousePressEvent( e ); }
signals:
void itemClicked();
};namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{
Q_OBJECTpublic:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();private:
QGraphicsScene *scene;
QGraphicsView *view;private slots:
void onItemClicked();
};#endif // MAINWINDOW_H
@source:
@
#include "mainwindow.h"
#include <QDebug>MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{view = new QGraphicsView(); scene = new QGraphicsScene(); view->setScene( scene ); view->setSceneRect( view->rect() ); scene->setSceneRect( view->rect() ); scene->setBackgroundBrush( Qt::white ); setCentralWidget( view ); TextItem *t = new TextItem( "Item 1" ); TextItem *t2 = new TextItem( "Item 2" ); scene->addItem( t ); scene->addItem( t2 ); t->setPos( scene->sceneRect().topLeft() ); t2->setPos( scene->sceneRect().center() ); QObject::connect( t, SIGNAL(itemClicked()), this, SLOT(onItemClicked()) ); QObject::connect( t2, SIGNAL(itemClicked()), this, SLOT(onItemClicked()) );
}
void MainWindow::onItemClicked()
{
TextItem ti = qobject_cast<TextItem>( sender() );
if ( ti != 0 ) {
qDebug() << PRETTY_FUNCTION << ti->document()->toPlainText();
}
}
@Please note the "Optional" commented code, uncomment them to se the change.
Of course you can use signal mapper and many more to get it better, it's just an idea.By the way. I strongly recommend the "Diagram Scene example":http://doc.qt.nokia.com/4.7-snapshot/graphicsview-diagramscene.html.
Hope that helps.