Pmw ScrolledCanvas: How to scroll to specific item?

MrBlueSky penneys at bigfoot.com
Mon Jun 5 11:07:51 EDT 2006


MrBlueSky wrote:
> Hi, I've got a ScrolledCanvas object (sc) and have identified an item
> on the canvas to which I wish to scroll.  I've been reading around and
> experimenting but with not much success.
>
> So far I've managed to get the item's bbox using sc.bbox(item)
> And got the proportion of the canvas that's visible using sc.xview()
> and sc.yview()
> And established the whole canvas bbox using sc.bbox(ALL)
>
> I've even gone on to use some rudimentary maths to work out whether I
> need to scroll, then used:
> sc.xview_moveto(itemX)
>
> But this is all rather messy and I've not yet got it working.
> There must be an easier way?!
>
> Thanks!
>
> John

Done it!  I realised that searching for the way to do this using Tk
would give me the clue.
For the benefit of any other poor soul who wants to do this, here's my
code:

    def scrollToItem(self, item):
        """Work out whether the specified item is on display.
        If it's not, scroll to it."""

        # Bounding box for the item
        xItemMin, yItemMin, xItemMax, yItemMax = self.bbox(item)

        # Find out what proportion (0.0 to 1.0) of the canvas is
        # currently on view
        xViewMinP, xViewMaxP = self.xview()
        yViewMinP, yViewMaxP = self.yview()

        # Find out the full extent of the canvas
        scrollRegionStr = self.component("canvas").cget("scrollregion")
        scrollRegionElementsStr=scrollRegionStr.split(' ',4)
        xCanvasMin = float(scrollRegionElementsStr[0])
        yCanvasMin = float(scrollRegionElementsStr[1])
        xCanvasMax = float(scrollRegionElementsStr[2])
        yCanvasMax = float(scrollRegionElementsStr[3])
        xRange = float(xCanvasMax - xCanvasMin)
        yRange = float(yCanvasMax - yCanvasMin)

        # Work out the canvas coordinates of the bit of the canvas
that's
        # currently on view
        xViewMin = float(xViewMinP)*xRange
        xViewMax = float(xViewMaxP)*xRange
        yViewMin = float(yViewMinP)*yRange
        yViewMax = float(yViewMaxP)*yRange

        if xItemMin < xViewMin:
            newXViewP = float(xItemMin - xCanvasMin)/xRange
            self.xview_moveto(newXViewP)
        elif xItemMax > xViewMax:
            newXViewP = float(xItemMax - xCanvasMin -
(xViewMax-xViewMin))/xRange
            self.xview_moveto(newXViewP)

        if yItemMin < yViewMin:
            newYViewP = float(yItemMin - yCanvasMin)/yRange
            self.yview_moveto(newYViewP)
        elif yItemMax > yViewMax:
            newYViewP = float(yItemMax - yCanvasMin -
(yViewMax-yViewMin))/yRange
            self.xview_moveto(newYViewP)

(I'd still very much appreciate any critique of this!)

John




More information about the Python-list mailing list