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

Thomas Fjellstrom tfjellstrom at shaw.ca
Sat Jan 23 12:37:52 CET 2010


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 :( ).

-- 
Thomas Fjellstrom
tfjellstrom at shaw.ca




More information about the Qt-interest-old mailing list