PDA

View Full Version : what item QCanvasItemList is holding..



Kapil
21st April 2006, 10:23
Hi..

Is their any way to find out what item the QCanvasItemList is holding..
i read th class well but couldn't find any function supporting it..
with rtti() i can find out what item type it is holding but not exactly which item..
i want to extract the exact item which it is holding...
Is it possible????

Thank you...

with regards,
Kapil

wysota
21st April 2006, 10:51
with rtti() i can find out what item type it is holding but not exactly which item..

Sure, compare pointers from the list and from the set of items you have stored in the canvas (QCanvas::allItems()).

Kapil
21st April 2006, 11:24
Sure, compare pointers from the list and from the set of items you have stored in the canvas (QCanvas::allItems()).


Are you talking about the collideswith() function of the QCanvasItem to find out the item clicked..
If yes, then i tried it out but then it is not returning me the item which i have clicked but the first item on the canvas.. dont know why ?????

Kapil

wysota
21st April 2006, 11:35
I don't quite understand your problem. If you want an item clicked, just call QCanvas::collisions(const QPoint &p) with p set to the coordinates of the click (e->pos() if in mouse press event) and it returns a list of pointers to items. Then just iterate the list and do with the items whatever you want. You can take a look at wwWidgets (http://www.wysota.eu.org/wwwidgets) widget set, it contains a canvasview with dragging capabilities (among other things it contains a handler for clicking items).

Kapil
21st April 2006, 11:46
This is the code of what i have done and is exactly what u have asked me to...



void ImageDraw::selectLine(QPoint pRelease)
{
int i=0;
QPoint xPoint,yPoint;
Q3CanvasItemList item = m_pCanvas->collisions(pRelease);;
m_itemLine = item;
for (Q3CanvasItemList::Iterator it= m_itemLine.begin(); it!= m_itemLine.end(); ++it)
{
if ( (*it)->rtti() == 7 )
{
for(i=0;i<20;i++)
{
if((i<lineList.size())&&((*it)->collidesWith(lineList.at(i))))
{
QMessageBox::information(this, tr("Mouse Event"),tr("Line %1 Mouse Event Handled ").arg(i));
m_pCanvasLine[i]->setPen(QPen(Qt::red));
xPoint = m_pCanvasLine[i]->startPoint();
yPoint = m_pCanvasLine[i]->endPoint();
m_pCanvasLine[i]->setPoints(xPoint.x(),xPoint.y(),yPoint.x(),yPoint. y());
m_pCanvasLine[i]->show();

break;
}
else if((i<lineList2.size())&&((*it)->collidesWith(lineList2.at(i))))
{
QMessageBox::information(this, tr("Mouse Event"),tr("Line %1 Mouse Event Handled ").arg(i));

m_pCanvasLine2[i]->setPen(QPen(Qt::red));
xPoint = m_pCanvasLine2[i]->startPoint();
yPoint = m_pCanvasLine2[i]->endPoint();
m_pCanvasLine2[i]->setPoints(xPoint.x(),xPoint.y(),yPoint.x(),yPoint. y());
m_pCanvasLine2[i]->show();

break;
}

}
}


Note : sorry as i have pasted the same code in some other thread but the doubt was a bit different... so if u think that this is turning out to be a double thread then you can close it.. sorry again.. the thread is in the Qt Programming section with the name Highlighting the CanvasItem....

Thank you...

Kapil

wysota
21st April 2006, 12:23
What for are you using this collidesWith?

Try something like this:


void ImageDraw::selectLine(QPoint pRelease){
Q3CanvasItemList itemlist = m_pCanvas->collisions(pRelease);
for (Q3CanvasItemList::Iterator it= itemlist.begin(); it!= itemlist.end(); ++it){
Q3CanvasItem *item = *it;
if(item->rtti()!=7) continue;
Q3CanvasLine *line = (Q3CanvasLine*)item;
line->setActive(true);
}

Kapil
21st April 2006, 12:47
hi..

thanks a lot for the code..
yes is helps me selecting the exact line but then there is a small problem again...

why is so that after i click on any item it is getting disappeared... the moment i click on the line it goes off...
i tried setting the line color to some other color other than white but still the line is gone the moment i click on it... why is it so????

Kapil

wysota
21st April 2006, 14:25
Where do you "set" the colour? AFAIR canvas items don't have a colour associated with them. I think you need to subclass the item and reimplement its painting routine to be able to change the colour of an item.

For example:


void MyCanvasLine::draw ( QPainter & painter ){
if(isActive()) painter.setPen(Qt::red);
QCanvasLine::draw(painter);
}

Kapil
24th April 2006, 10:53
hi..

to set the colour i did something like this and its working


Q3CanvasLine *m_pCanline = (Q3CanvasLine*)itemCan;
m_pCanline->setPen(QPen(Qt::red));
xPoint = m_pCanline->startPoint();
yPoint = m_pCanline->endPoint();
m_pCanline->setPoints(xPoint.x(),xPoint.y(),yPoint.x(),yPoint. y());
m_pCanline->show();


The drawback which i found with this approach was that i have to redraw the line...

There is a small bug which is appearing while highlighting the lines.. at a point whenever there are more than 2 lines intersecting i.e. when it tells that canvasitemlist size is 3+, it does not color the line on which i have clicked but colours any of the lines surrounding the point...
The reason what i thought could be the settings of the z-coordinate... it fills the canvasitemlist in the form of a stack and colours the topmost elemnt of the stack whenever they are more than 1...
the problem is that how do i figure it out that at what index does my item (one i have clicked) lie in the canvasitemlist so that i can colour that particular item...
I tried to put on what not mathematical formualtions but few seem to work for a particular set of points and not for the general standards...
How do i get rid of this problem...:confused:

Thank you...

with regards,
Kapil

wysota
24th April 2006, 12:09
Maybe something like this would be easier:


Q3CanvasLine *m_pCanline = (Q3CanvasLine*)itemCan;
m_pCanline->setPen(QPen(Qt::red));
m_pCanline->invalidate();
m_pCanline->update();


the problem is that how do i figure it out that at what index does my item (one i have clicked) lie in the canvasitemlist so that i can colour that particular item

If you click on a canvas, you get a list of all items which collide with that point. So you click on each of the lines returned.

Kapil
24th April 2006, 13:07
click on each of the lines returned.
Sorry but i could not understand by the statement... you want to say that highlight all the items that collide with the point...

when i click on the canvas it returns me the point with the of which i extract all the canvas items coliiding with the point...
now i need to highlight only one particular item of all that collide with the point.. if i highlight all of the items then it doesn't solve the purpose..
its like user clicks on the line, chooses the color and the line is coloured that ways... this is what i am not able to do.. was still working out with it....????????
is their any way to sort it out...

thank you,

with regards,
Kapil

wysota
24th April 2006, 14:41
I don't exactly understand your problem... This is how I do it in wwWidgets (http://www.wysota.eu.org/wwwidgets):


void wwCanvasView::contentsMousePressEvent( QMouseEvent * e ) {
if(e->button()!=LeftButton || !canvas())
return QCanvasView::contentsMousePressEvent(e);
QWMatrix wm = inverseWorldMatrix();
QPoint pt = wm.map(e->pos());
QCanvasItemList l = canvas()->collisions(pt);
if(l.empty()) {
emit clicked(0);
return QCanvasView::contentsMousePressEvent(e);
}
if(!m_dragsEnabled) {
emit clicked(l.first());
return QCanvasView::contentsMousePressEvent(e);
}
QCanvasItem *clicked_item = l.first();
m_dragged = clicked_item;
m_dragorig = pt;
emit clicked(clicked_item);
}

In your case I would use something like this:


void someClass::contentsMousePressEvent( QMouseEvent * e ) {
if(e->button()!=LeftButton || !canvas()) // if not left button or no canvas assigned
return QCanvasView::contentsMousePressEvent(e); // ignore the event
QWMatrix wm = inverseWorldMatrix(); // inverse the matrix to allow zooming
QPoint pt = wm.map(e->pos()); // map the point according to the matrix
QCanvasItemList l = canvas()->collisions(pt); // get list of items clicked
if(l.empty()) { // if none clicked
return QCanvasView::contentsMousePressEvent(e); // ignore event
// in your case you could "deselect" all items, if you want
}
QCanvasItem *clicked_item = l.first(); // get the top most clicked item
clicked_item->setPen(Qt::red); // change it to be red
clicked_item->invalidate(); // invalidate it so that it gets redrawn
clicked_item->update(); // update the canvas to reflect changes
}

In my opinion this is all that should be done to highlight a "clicked" item.

Kapil
24th April 2006, 14:47
Hi..

A minor doubt about the use of the invalidate and the update functions of the Q3CanvasPolyganItem..
i tried using them but the error was thrown that they are the protected members hence cannot be used directly.. so this means that i need to inherit the Q3CanvasPolyganItem class in order to use these functions... I am already inhereting the Q3CanvasView class.. Wont it create any errors

wysota
24th April 2006, 15:25
You have to update the canvas, so from within the view you should call canvas()->update(). You can use Q3Canvas::setAllChanged() instead of invalidate() if setPen doesn't invalidate the item by itself.

Kapil
25th April 2006, 10:11
QCanvasItem *clicked_item = l.first(); // get the top most clicked item

I don't know why it is not colouring the item i clicked but colouring some other item on the canvas...
I would put the image here.. i hope this would help you to understand what exactly is happening.. i have pointed out the linei have clicked and u can see the line which it has coloured....

wysota
25th April 2006, 10:52
Maybe you're mixing the coordinates somewhere? It looks like your horizontal and vertical coords are inverted -- (y,x) instead of (x,y).

Kapil
25th April 2006, 12:45
Maybe you're mixing the coordinates somewhere? It looks like your horizontal and vertical coords are inverted -- (y,x) instead of (x,y).

Hi..

its not inverted... i have created them seperately, though it gives the look that ways as the symmetry is maintained... dont even know which part of the code would give you the idea of how to sort it out....

i am totally confused... would try it out in a different manner by giving it some break.. i hope it sorts out the things...

Thanks a lot for all the help and sample code you provided.. It really helped a lot...

take care...

with regards,
Kapil

wysota
25th April 2006, 14:57
Try with a single line. If it works, add another and try again. Report coordinates of every click through qDebug or QMessageBox, etc.