1 Attachment(s)
select QGraphicsItems by mouseclick
I wana to select QGraphicsItems by mouseclick, and then generate new QGraphicsItems as children of the one being clicked. It's supposed to be like this:
I used to look for signals like isSelected or something, of course with no luck. Since QGraphicsItem even doesn't inherit QObject.
Now I have no idea of how it could be implemented. Can anyone help?
Many thanks in advance!
Re: select QGraphicsItems by mouseclick
BTW, the rectangle is drawn this way:
Code:
void test
::drawRect(QGraphicsScene &scene,
int x,
int y,
int m,
int n
) {
i
->setBrush
( QColor(233,
104,
21) );
i->setZValue(2);
}
Re: select QGraphicsItems by mouseclick
You can use, QGraphicsScene::selectionChanged() signal and use QGraphicsScene::selectedItems() to get the selected item.
One more better way is to subclass the required QGraphicsItems and provide the required functionality using mouse*Event handlers. Or may be implement QGraphicsItem::itemChange() to intercept selection and then take required action.
Finally if you dont want to reimplement each and every shape items, you can create a custom item , implement the QGraphicsItem::sceneEventFilter() method to do appropriate things on mouse click and install this as event filter. (see QGraphicsItem::installSceneEventFilter( ) )
Re: select QGraphicsItems by mouseclick
Gopala Krishna, Thanks for your quick reply!
I tried the first way u gave:
Code:
test
::test(QWidget *parent, Qt
::WFlags flags
){
ui.setupUi(this);
......
ui.graphicsView_3->setScene(&scene3);
QObject::connect(&scene3,
SIGNAL(selectionChanged
()),
this,
SLOT(testslots
()));
}
Code:
{
i->setPos(x, y);
i->setZValue(3);
}
Code:
void test::testslots()
{
drawText(scene3, &tmp, 0, 0);
}
But after I change the selection, I mean I select the items one by another, nothing happens !:confused:
Is there anything wrong ?
Re: select QGraphicsItems by mouseclick
Is the slot being called atleast once ? I am asking this because the docs for selectionChanged() signal quote
Quote:
QGraphicsScene emits this signal only once for group selection operations. For example, if you set a selection area, select or unselect a QGraphicsItemGroup, or if you add or remove from the scene a parent item that contains several selected items, selectionChanged() is emitted only once after the operation has completed (instead of once for each item).
A better way to verify if the slot was called is to use qDebug() in the slot.
Re: select QGraphicsItems by mouseclick
Checkout this. This example works for me
object.h
Code:
#include <QObject>
#include <QMessageBox>
{
Q_OBJECT
public:
{}
public slots:
void test()
{
}
};
main.cpp
Code:
#include <QtGui>
#include "object.h"
int main(int argc, char *argv[])
{
Receiver r;
QObject::connect(&sc,
SIGNAL(selectionChanged
()),
&r,
SLOT(test
()));
v.show();
return app.exec();
}
Re: select QGraphicsItems by mouseclick
I checked the reference and found that the selectionChanged() signal is introduced since Qt4.3, and I am using Qt4.2 now:crying:
Re: select QGraphicsItems by mouseclick
In that case you are better of to reimplement the item's itemChange method. Actually you can derive your item even from QObject and you can emit custom signal when selection changes.
Code:
{
Q_OBJECT
public:
MyCustomItem()
..
signals:
void selectionChanged(bool newState);
protected:
{
bool newState = value.toBool();
//This sometimes might not be safe to emit signal
//here since the state is still unchanged. Better option might
//be to use a single shot timer to emit this signal rather than
//emitting it directly
emit selectionChanged(newState);
}
}
};
P.S: I'm not sure of my comment in the program though :)
Re: select QGraphicsItems by mouseclick
Another way of catching events is -
Install filter on the scene, check if any item is presnt where the mouse is pressed. U can get the item by itemAt() function, and then perform the action u want.
However from the thumbnail I see u have more of a tree structure kind items.
I want to know why arent u using a tree itself ?? U can create a custom QTreeWidgetItem and have a pointer to the QGraphicsItem to it..
like -
class MyTreeWidgetItem : public QTreeWidgetItem
{
QGraphicsItem *pGraphicsItem;
};
and u can have a map of graphics items and tree nodes -
QHash <QGraphicsItem *, MyTreeWidgetItem*> item_treeMap;
Hope I am getting ur problem correctly .
Re: select QGraphicsItems by mouseclick
Quote:
Originally Posted by
aamer4yu
Another way of catching events is -
Install filter on the scene, check if any item is presnt where the mouse is pressed. U can get the item by itemAt() function, and then perform the action u want.
I guess this might not work. Actually even i stated above that eventFilter is an alternative.
Since the event filter is called before the event handlers the item wont be selected when mouse is pressed and control reaches eventFilter. So you have no way here to determine whether the item is selected or not. You cant even execute the event handler in eventfilter since the handlers are protected/private.
Please correct me if i am wrong :)
EDIT: Sorry misread your post. You select the item just by coordinate right(using itemAt). I thought you were looking at selectedItems in the event handler. But you have to make sure that you are checking the button and also set the state of the item to selected.
Re: select QGraphicsItems by mouseclick
I did what u said
Code:
{
Q_OBJECT
public:
MyRectItem();
signals:
void selectionChanged(bool newState);
protected:
{
{
bool newState = value.toBool();
emit selectionChanged(newState);
}
}
};
Code:
void test
::drawRect(QGraphicsScene &scene,
int x,
int y,
int m,
int n
) {
MyRectItem
*i
= scene.
addRect( QRectF(x, y, m, n
));
i
->setBrush
( QColor(233,
104,
21) );
i->setZValue(2);
}
and there is an error :
error C2440: 'initializing' : cannot convert from 'QGraphicsRectItem *' to 'MyRectItem *'
How can I deal with this ?
I am not familiar with the multi-inheritance.
Hope you can help me, and thanks in advance.
Re: select QGraphicsItems by mouseclick
The scene.addRect returns new QGraphicsRectItem* which is now way connected to MyRectItem other than that they both have common base.
To add any of your custom item use scene.addItem(new CustomItem()) (in your case new MyRectItem).
One more thing , you don't seem to store any rect coordinates nor provide the required constructor. One way to tackle this is to inherit MyRectItem from QGraphicsRectItem rather that QAbstractGraphicsShapeItem and implement the constructors as needed :)
Re: select QGraphicsItems by mouseclick
I inherite MyRectItem from and implement the constructor
Code:
{
Q_OBJECT
public:
MyRectItem(int x, int y, int w,int h)
{
}
....
};
and then
Code:
void test
::drawRect(QGraphicsScene &scene,
int x,
int y,
int m,
int n
) {
MyRectItem *i = new MyRectItem(x, y, m, n);
scene.addItem(i);
}
But there is no Rect now:crying:
Re: select QGraphicsItems by mouseclick
I guess the following changes will fix your code
Firstly your constructor
and secondly set some pen and brush to the item
Code:
i
->setPen
(QPen(Qt
::darkBlue));
Re: select QGraphicsItems by mouseclick
Yes I 've set pen and brush to the item, I discard them just to make my post short:)
And I revise the constructor as u said and it works !
Thanks a lot :D
the next problem is that :
seems no signal is emited ?
because when I select the MyRectItems one after another, and nothing happens? :confused::(
Singal and Slot definition and connection is as below.
Latest:
Code:
void test
::drawRect(QGraphicsScene &scene,
int x,
int y,
int m,
int n
) {
MyRectItem *i = new MyRectItem(x, y, m, n);
QObject::connect(i,
SIGNAL(selectionChanged
()),
this,
SLOT(testslots
()));
scene.addItem(i);
....
}
Now it is OK ~
Re: select QGraphicsItems by mouseclick
You used the wrong signature of signal in the connect statement.
Shouldn't that be SIGNAL(selectionChanged(bool)) ?
Re: select QGraphicsItems by mouseclick
Yes, I also change the signal to make it more simple...
The problem is that the signal is emited whenever the selection of an item is changed, which also means that when I unselecte the item, the signal will also be emited.
This is not the what I want, which I want exactly is that when I selected an item, which would be better, double click an item, there can be a signal, and then I can write some slots to deal with this signal.
Re: select QGraphicsItems by mouseclick
Thats very easy to fix:)
Code:
if(newState == true)
emit itemSelected();
Notice that i changed the signal name to be more meaningful. Change everywhere as needed :)
Re: select QGraphicsItems by mouseclick
Thanks a lot !
It works fine.
Anyway, if I want to selected that item by double click, what should I do ?
PS:seems I am really lazy. But maybe I should know the way to do it first, then I can find out why I should do it that way, right ?:p
Re: select QGraphicsItems by mouseclick
I guess you can do it yourself if you get to know some common mistakes ;)
Anyway for your question the answer involves
QGraphicsItem::mouseDoubleClickEvent()
QGraphicsItem::setSelected()
I hope you got the approach :)
Re: select QGraphicsItems by mouseclick
hehe.
Anyway, thanks a lot for your great patience.:D