PDA

View Full Version : How to draw QGraphicsItem at the same location?



jeanremi
25th August 2011, 00:32
H'llo there,

I'm trying to paint a QGraphicsItem to stay at the top edge of my view, but when I scroll the view down, the item scrolls off the view.
I have connected the vertical scroll bar valueChanged() function to call my slot:


// vertical_scroll is the slot that gets called
// ival comes from valueChanged(int)
void my_graphics_item::vertical_scroll(int ival)
{
int top = pgraphicsview->viewport()->rect().top();
this->moveBy(0, top);
this->update();
}


1/ when this slot is called, why is top always 0? (the view is scrolled down, but this is always returned as 0)
2/ when I use ival instead of top, item moves down in big steps.
3/ how do I solve this issue? What am I doing wrong?

I just want the item to stay in view regardless of my scrolls (top, right, left or bottom).

Many thanks
Jean

norobro
25th August 2011, 04:00
Try putting your slot(s) in your view. e.g.
void pgraphicsview::vertical_scroll(int vPos){
int hPos = horizontalScrollBar()->value();
my_graphics_item->setPos(hPos, vPos);
}
Create another slot for horizontal scrolling. Using the passed parameter(s) should keep the item in the upper left corner. Adjust to suit.
HTH

wysota
25th August 2011, 07:58
1/ when this slot is called, why is top always 0? (the view is scrolled down, but this is always returned as 0)
Because it is the top of the viewport (the widget actually showing the graphics scene) and not the scene, thus the top is always 0.

2/ when I use ival instead of top, item moves down in big steps.
You don't want to use that.


3/ how do I solve this issue? What am I doing wrong?
What kind of item is that? Maybe it shouldn't be an item at all? Items are tied to the scene and not to the view.

jeanremi
25th August 2011, 09:59
Good morning and thank you for your answers.

To norobro:
vertical_scroll is effectively called from graphicsview when its vertical (and horiz.) scroll bar's value changes. As you suggest, setPos(x,y) is probably what I need to call instead of moveBy(x, y);
( I will try this as soon as I get back from work ;-) )

To Wysota:
You have now spurred my curiosity about the graphicsview's viewport. If its top is always 0 when the view is scrolled up or down, does it mean that it is the scene which is moving ? (I was under the impression that the viewport should be the one moving)
In other words, what happens to the viewport when a user scrolls down/up?

The item is derived from QGraphicsItem as usual and it is added to scene as one would expect.
class my_graphics_item: public QGraphicsItem
....
my_graphics_item* test = new m_graphics_item(parent);
pscene->addItem(test);


(I will post my results later tonight)

Thanks,
Jean

wysota
25th August 2011, 10:58
You have now spurred my curiosity about the graphicsview's viewport. If its top is always 0 when the view is scrolled up or down, does it mean that it is the scene which is moving ? (I was under the impression that the viewport should be the one moving)
The view's projection matrix changes. You could say that it is the scene that moves (the same way the train station seems to move when you are sitting in the train and looking through the window).


In other words, what happens to the viewport when a user scrolls down/up?
Nothing. It only gets redrawn.


The item is derived from QGraphicsItem as usual and it is added to scene as one would expect.
I understand that. My point is that it should probably not be an item at all. If it is non-interactive, it's easiest to just subclass QGraphicsView, reimplement its paintEvent and simply paint on the viewport whatever you need painted after calling the base class implementation (so that graphics view paints the scene first).

jeanremi
25th August 2011, 12:07
The view's projection matrix changes.
I see. This makes a lot of sense now. Ok point taken. ;-)


If it is non-interactive, it's easiest to just subclass QGraphicsView, reimplement its paintEvent and simply paint on the viewport whatever you need painted after calling the base class implementation (so that graphics view paints the scene first).

This is a very good suggestion, but the item will be an interactive one. A user will be able to click on it in order to relocate the view elsewhere. I should remember this suggestion for non-interactive ones.
However why would this suggestion only be good for non-interactive items? what's the limitation?

Many thanks,
Jean

PS: I haven't tested with setPos(x, y) yet. Still to come.

jeanremi
25th August 2011, 19:06
Hi,

norobro:
setPos(hPos, vPos); has effectively solved this issue very well.

wysota:
If I had more time I would try the qgraphicsview subclassing. I believe it would also work.

Thank you all for your endeavouring inputs :-D

Until then,
Jean

wysota
25th August 2011, 22:59
However why would this suggestion only be good for non-interactive items? what's the limitation?
For interactive items you also need to reimplement other events :) There is an alternative though. Make your navigation thingy a widget and position it in the viewport. I guess that's the easiest and prettiest solution.

Zikoel
20th September 2011, 13:38
Hi,

I have the same problem. I have an Item that must stay always on top edge of an viewport. I want try whit a widget on my viewport but I have some problem.



void CMCanvasManager::createMenu(QWidget *canvas_parent)
{
QWidget *w=new QWidget(canvas_parent, Qt::Popup | Qt::WindowStaysOnTopHint);
w->setGeometry(100, 100, 100, 100);
w->setMaximumSize(100,100);
w->setMinimumSize(100,100);
w->setFocusPolicy(Qt::NoFocus);
w->show();
}


Whit the code above I expect that my popup widget stay at 100,100 respect the parent geometry, but this does not happen. The widget appear at 100,100 respect the desktop, olso if I click on viewport the popup disappear. Any advice?

wysota
20th September 2011, 14:14
What is canvas_parent? And why are you setting those flags in the constructor?

Zikoel
20th September 2011, 14:28
canvas_parent is the widget that contain my custom QGraphicsView class, and I have set the flags in the costructo because I thought it was the best way to do it. I think that I have wrong all.
I am proceeding to attempts because I did not quite clear how the widgets work. Sorry.. Councils do what I described? Thank you!

wysota
20th September 2011, 15:13
canvas_parent is the widget that contain my custom QGraphicsView class
So how is this supposed to work? Do you understand the relationship between a widget and its parent?

I think that I have wrong all.
I think so too :)


I am proceeding to attempts because I did not quite clear how the widgets work. Sorry.. Councils do what I described? Thank you!

Looking at my earlier explanation, I write that you should position the widget on the viewport. To do that the widget needs to be a child of the viewport, not of an arbitrary widget.

If you have no idea about how things work, kindly please consider posting in the Newbie section and please be very explicit about what you are doing, it will save you a lot of time.

Zikoel
20th September 2011, 15:44
When I say "I am proceeding to attempts because I did not quite clear how the widgets work" I mean that I do not know the widget, but I work with Qt at least a year ;D.

I have modified the code in this mode:



void CMCanvas::createMenu(){
m_menu_canvas=new QWidget();
m_menu_canvas->setWindowFlags(Qt::Window | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint);
m_menu_canvas->setGeometry(100, 100, 100, 100);
m_menu_canvas->setMaximumSize(100,100);
m_menu_canvas->setMinimumSize(100,100);
m_menu_canvas->show();
}
void CMCanvas::destroyMenu(){
m_menu_canvas->close();
}


The two metod is inside my custom class of QGraphicsView, but I do not know how to anchor the two windows.

wysota
20th September 2011, 16:08
Please get familiar with the concept or parent-child relationship between widgets. And I don't mean Qt but rather the GUI architecture currently used on desktop systems. So far you are trying to stack two top-level windows on top of each other which is unlikely to do what you want. Of course unless you want something else than what this thread is about.