installing event filters in QT - qt

I am trying to avoid wasting time doing something if my lack of knowledge of QT could avoid me even to try.
Supposed a have a class X not derived from QGraphicsItems with fields containing among others several QGraphicsItems. Can I define event filters in X and install them on the QGraphicsItems in order to let X receive the event before the QGraphicsItems themselves?
Thanks.

If your design allows, rather than objects inheriting from QGraphicsItem, inherit from QGraphicsObject, which will allow you to use the standard QObject::installEventFilter.
Otherwise, you would need to have class 'X' inherit from QGraphicsItem.
Then, you can install an event filter from one GraphicsItem to another through the QGraphicsScene. This is detailed in the Qt Documentation here.
To filter another item's events, install this item as an event filter for the other item.
Example:
QGraphicsScene scene;
QGraphicsEllipseItem *ellipse = scene.addEllipse(QRectF(-10, -10, 20, 20));
QGraphicsLineItem *line = scene.addLine(QLineF(-10, -10, 20, 20));
line->installSceneEventFilter(ellipse);
// line's events are filtered by ellipse's sceneEventFilter() function.
ellipse->installSceneEventFilter(line);
// ellipse's events are filtered by line's sceneEventFilter() function.

Related

Get object handler user clicked in scene

QList<QWidget *> list;
In scene user can add no of objects and m storing objects in list. i want to get the object the user clicked or focused one so that i can change properties or delete object. how to get clicked object pointer from list ?
QWidget might not have the signals and methods you need to implement this easily.
Look here http://doc.qt.io/qt-5/widget-classes.html to find the widget best suited for your needs.
In order to keep track for the signals and to which button they belong you can want use a QSignalMapper.

QAbstractItemModel in QGraphicsView

I have to create items based on the file system in the directory. it is mandatory that i have to use QGraphicsView and not (QTreeView/QListView) so how i can manage to hold a QModel for the graphicsScene. can any one help me suggest or refer an example of how i can load QFileModel with the QGraphicsScene.
There is only one easy way to do this, add view with model to the scene. Yes, it is still QTreeView/QListView, but you get all advantages of QGraphicsView and QGraphicsScene, such as rotation, interaction etc.
//fill the model and set model to view
ui->tableView->setParent(0);
QGraphicsProxyWidget * proxyView = ui->graphicsView->scene()->addWidget(ui->tableView);
proxyView->setRotation(45);
Result:
You don't need QFileModel for it. Use QDir::entryInfoList to get list of files and QFileSystemWatcher to track modification of file system.

QwtPlot how to select point(s) curve

I have a QwtPlot that contains some curves and I would like to be able to get the selected point(s) (and curve pointer) from these curves : select a point by clicking and select points by dragging a rect.
I use the following code:
// Picker with click point machine to provide point selection
QwtPlotPicker* clickPicker = new QwtPlotPicker(this->canvas());
clickPicker->setStateMachine(new QwtPickerClickPointMachine);
clickPicker->setMousePattern(0,Qt::LeftButton,Qt::SHIFT);
connect(clickPicker, SIGNAL(appended(QPointF)),
this, SLOT(pointSelected(QPointF)));
// Picker with drag rect machine to provide multiple points selection
QwtPlotPicker* rectPicker = new QwtPlotPicker(
this->xBottom, this->yLeft, QwtPicker::RectRubberBand,
QwtPicker::AlwaysOff, this->canvas());
QwtPickerDragRectMachine* test = new QwtPickerDragRectMachine();
test->setState(QwtPickerMachine::RectSelection);
rectPicker->setStateMachine(test);
connect(rectPicker, SIGNAL(selected(QRectF)),
this, SLOT(pointsSelected(QRectF)));
but the pointSelected slot is called every time I click on the QwtPlot and not only on a curve
BTW, I also try to connect a slot to the signal QwtPlotPicker::selected(const QVector &pa) but it is never emitting ...
I think it is more convenient to use the CanvasPicker as it comes with the examples and can be extended easily.
Please have a look at the event_filter which comes with Qwt. You should use the class CanvasPicker (it is not part of the Qwt API, but you'll find the code in the examples).
You can instantiate it in your class using
picker = new CanvasPicker(plot); // plot is a pointer to your instance of QwtPlot
You'll see that the event filter is installed in the constructor of CanvasPicker.
Now have a look at CanvasPicker::eventFilter(QObject *object, QEvent *e) which is called when an event occurs in the event loop of QwtPlot. Implement your application logic in the switch construct, f.i. change case QEvent::MouseMove:.

Dragging multiple QGraphicsItems in different QGraphicsScenes for the same amount

I have my own classes (MyGraphicsScene, MyGraphicsView, MyGraphicsItem) derived from QGraphicsScene, QGraphicsView and QGraphicsItem.
In my main window, I then create nine (9) instances of MyGraphicsScene, shown through nine instances of MyGraphicsView. All nine MyGraphicsScenes contain pointers to each other.
How can I drag an instance of MyGraphicsItem in one MyGraphicsScene, and then automatically drag certain MyGraphicsItem instances (in the eight remaining MyGraphicsScenes) for the same amount/distance/vector?
My first idea was to reimplement MyGraphicsItem::itemChange (with change == QGraphicsItem::ItemPositionChange) and then call setPos() for remaining instances of MyGraphicsItem (contained within other MyGraphicsScenes). However this won't work because I will get infinite recursion (setPos() would trigger itemChange() as well, including for the originating MyGraphicsItem).
Any other ideas from experienced Qt-ers?
I do know for a fact you can use the same QGraphicsScene in multiple views. So if you're just trying to have multiple views of the same thing, call MyGraphicsView all with the same scene.
If you define derived class for QGraphicsItem (I think you already have, right?) and reimplement the mouseMoveEvent so it calls the move method to all 9 objects.
Remember that you have at your disposal all the attributes of QMouseEvent, e.g. buttons(), pos().
void MyGraphicsItem::mouseMoveEvent( QMouseEvent *event )
{
if (event->buttons() & Qt::LeftButton) {
QPoint pos = event->pos();
// ...
}
}
Hope that helped!

Sharing same model in two QGraphicScene instances in Qt

I have an application that displays an editor for a diagram using QGraphicsScene object. I would like to create a read only version of the same dialog but have ability for user to see both at the same time.
SimScene* pScene1 = new SimScene(model); // adds model to scene
SimScene* pScene2 = new SimScene(model); // adds model to scene
QGraphicsView* pView1 = new QGraphicsView();
pView1->setScene(pScene2);
QGraphicsView* pView1 = new QGraphicsView();
pView2->setScene(pScene2);
When I create 2 instances of QGraphicsScene and use addItem on the second one it removes all the items from the first one. Does Qt support any sort of sharing of model between scenes? Is my only choice to have same scene and try to customize the view? Later one doesn't seem to work because object selection information is within the graphics items being shared so if I disable flags on them they become read only in both views. Any advice is appreciated. Thanks.
If you just want an interactive and a read-only view on your model you can use a single QGraphicsScene and 2 QGraphicsViews. You just have to call QGraphicsView::setInteractive(false) on one of them. That way you don't have to change any item flags.
I think that you're storing QSceneItems in model classes. Because of that pScene1 and pScene2 are trying to share not only the model itself, but also the scene items. This won't work because any scene item can be placed only on one scene at any given moment.
How to fix it? Make model not aware of any GUI. Let it issue changed() notifications whenever something interesting happens.
Then let each SimScene wrap model into whatever QSceneItems it wants, and process changed() notifications.
Example:
Model:
Graph,
Edge,
Vertex
GUI
SimScene,
QEdge,
QVertex,
QSimInfo,
Qbackground, and so on ...
Also, you add pScene2 twice:
...
pView1->setScene(pScene2);
...
pView2->setScene(pScene2);
And allocate memory for the same pointer twice:
QGraphicsView* pView1 = new QGraphicsView();
...
QGraphicsView* pView1 = new QGraphicsView();

Resources