[Qt-interest] QGraphicsItem ignore scene translation/transform?

Thomas Fjellstrom tfjellstrom at shaw.ca
Sun Jan 24 12:56:02 CET 2010


On Sat January 23 2010, Thomas Fjellstrom wrote:
> On Fri January 22 2010, Thomas Fjellstrom wrote:
> > On Fri January 22 2010, Samuel Rødal wrote:
> > > ext Thomas Fjellstrom wrote:
> > > > On Fri January 22 2010, Samuel Rødal wrote:
> > > >> ext Thomas Fjellstrom wrote:
> > > >>> On Fri January 22 2010, Samuel Rødal wrote:
> > > >>>> Basically the
> > > >>>> top-level item is just an invisible item whose bounding rect is
> > > >>>> the same as the combined bounding rect of the child items (game
> > > >>>> squares). Whenever you earlier scaled / scrolled the view itself
> > > >>>> you'd now do the same with the top level item. You might wish to
> > > >>>> use QGraphicsScene::setSceneRect() to control which part of the
> > > >>>> scene should be mapped to the view at any time.
> > > >>>>
> > > >>>> I don't think this way of doing things should be significantly
> > > >>>> harder than changing the view transformation.
> > > >>>
> > > >>> But how to actually handle the events is something else. Right
> > > >>> now the child widgets all accept mouse events, which means the
> > > >>> parent widget doesn't get them, so it can't know when a person is
> > > >>> trying to scroll or zoom.
> > > >>>
> > > >>> I'm not sure how to have both, selecting the game elements, AND
> > > >>> letting the game board accept events to handle scrolling and
> > > >>> zooming.
> > > >>
> > > >> Not sure I understand from where you're currently triggering
> > > >> scrolling and zooming. Does each game square currently tell the
> > > >> view it needs to scroll or zoom? If so, can't you keep the current
> > > >> design but instead tell the invisible game board item to scroll /
> > > >> zoom?
> > > >
> > > > Sorry if I wasn't clear enough before.
> > > >
> > > > Right now the scrolling happens due to the QGV's own scroll bar.
> > > > Zooming would have (I haven't implemented it yet) been done with
> > > > the scroll wheel for now (and touch events in the future).
> > > >
> > > > Moving to keeping the scene's translation and transformation static
> > > > would mean disabling the view's scroll bar, and either implementing
> > > > my own, or scrolling by clicking anywhere on the "game board" and
> > > > dragging the board around (which is how it _will_ work on touch
> > > > based devices).
> > >
> > > Ah, that will be a problem yes. You'd have to set the scene rect to
> > > the bounding rect of the game board, but that means whenever
> > > graphicsview scrolls your non-transformable items will still be
> > > transformed. In that case I guess you can't avoid having to
> > > dynamically change the transformation of these items to have them
> > > match the current view (and you might as well go back to transforming
> > > the view directly in this case like you're already doing). Maybe
> > > there's a way to keep the item transformations and the view
> > > transformation in sync while avoiding any visual lag.
> >
> > I'm currently leaning towards disabling the view's scrollbars, and not
> >  using scene global translation or transformation. And having the Game
> >  Board widget handle scaling and scrolling with a sub item/widget.
> >  Possibly even going so far as to make the sub widget render and handle
> >  all the input for all squares, instead of using sub items. But I'm
> >  probably missing something that might cause that to not work.
> >
> > So basically it would work like this:
> >
> > ScrollZoomAreaItem contains my GameBoard item which contains zero or
> > more child widgets that get translated and transformed. The
> > ScrollZoomAreaItem widget will render any fancy scroll+zoom indicators
> > (ie: some kind of scroll bars, and zoom level indication), which
> > control the child's transform and translation matrix. The issue still
> > seems to be that the GameBoard will want to accept input, and so will
> > the ScrollZoomAreaItem. As I said before, this might be possible to
> > "fix" by cancelling any action on the GameBoard if any movement any
> > greater than some threshold is detected, and pass the events down to
> > the ScrollZoomAreaItem.. If possible.
> >
> > > Another option would be to not have these items be graphics items,
> > > but just draw them at static positions in
> > > QGraphicsView::drawForeground(). Then override graphics view's event
> > > handlers and only pass them on to the QGraphicsView base class if the
> > > event is not meant for any of the foreground "items".
> >
> > Hmm, how would one go about doing that when future items will be fairly
> > complex? Like an instant messaging interface, and a list of users in
> >  various "groups" you subscribe to. They absolutely need to accept
> > input, and I'd also like for them to animate fairly slickly (very easy
> > to do with 4.6!).
> >
> > The current user list and chat interface is really ugly, and sits in
> > QDockWidgets. I really want to move them into the GraphicsView, and be
> > themed along with the rest of the GraphicsView items I have (I wrote a
> >  set of Theme and Svg classes that are eerily similar to Plasma's Theme
> >  and Svg classes, but they work very well so I don't feel so bad about
> >  riping plasma off ;) ).
> 
> So, I've been doing some more thinking, if I go with just a single widget
> for the board, and have it handle its own rendering, translation and
> transformations, that would make it easy to fix the problem of who gets
>  what input. However I would be stuck having to do my own animations now.
>  I don't think I can use either of the two Animation APIs in Qt to
>  animate the squares on my board if I start doing everything manually.
>  This is sub optimal for a few reasons, mostly though because I'm really
>  bad at math, and would have a very hard time managing the animations
>  myself (the main reason I'm using Qt is so I don't have to do the hard
>  parts myself :( ).
> 

Ok, I think I've got a plan now that just might work.

Manually draw the board with a single "Smarter" widget that handles its own 
internal translation and transformation.

To do that I'd need to either not add the board square items to the board, 
and then draw each one manually when I think it might be dirty, or do the 
same, but make the BoardSquare's a plain QObject (instead of a 
QGraphicsWidget subclass ). Either way aught to work, and would result in 
the same api for the BoardSquares (paint()). Going either route is 
essentially the same, and would allow me to change very little in the 
existing BoardSquare class.

But it does mean I have to handle ALL hit testing and updating of the 
BoardSquares manually. Which I was trying really hard not to have to do.

Is a feature where an item is completely isolated from the scene 
transformation and translation likely to be added to Qt? I think it would be 
something that a lot of people would like very much.

-- 
Thomas Fjellstrom
tfjellstrom at shaw.ca




More information about the Qt-interest-old mailing list