Scaling\Zooming wx.DC

Hi All,

I’m using wx.PseudoDC to draw in my application.

I would like to implement a “ZOOM” option which should do the follow:

suppose i have image that captures the whole window and the same image in the virtual area (outside the viewable area?). when i press the zoom button, i would like to “shrink” both images in the Y axis by 1/2 so both pictures can be viewed.

any suggestion?

Thanks,

Roy.

roy zinn wrote:

I would like to implement a "ZOOM" option which should do the follow:
suppose i have image that captures the whole window and the same image in the virtual area (outside the viewable area?). when i press the zoom button, i would like to "shrink" both images in the Y axis by 1/2 so both pictures can be viewed.
any suggestion?

Use FloatCanvas -- you were really close, really!

Otherwise, you'll be re-implementing much of what's in there...

-CHB

···

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Christopher Barker wrote:

roy zinn wrote:

I would like to implement a "ZOOM" option which should do the follow:
suppose i have image that captures the whole window and the same image in the virtual area (outside the viewable area?). when i press the zoom button, i would like to "shrink" both images in the Y axis by 1/2 so both pictures can be viewed.
any suggestion?

Use FloatCanvas -- you were really close, really!

Otherwise, you'll be re-implementing much of what's in there...

If you decide to stick with DC's then look at SetUserScale.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Hi Chris, Robin,

As for float canvas, i’m still facing some problems with the coordinates system which is very important for my app, so i’m checking new ways (but maybe i’ll come back)

As for SetUserScale, well, wx.PseudoDC don’t have this attribute. What is the big benefit of the PseudoDC ? i started to use it because of the example in the wx docs and demos and it went well till that point.

speaking of the example, when i choose one of the items, it’s sometimes on top of other items and sometime behind, is there a way to bring it to the top once selected?

Thanks again,

Roy.

···

On Mon, Aug 11, 2008 at 10:21 PM, Robin Dunn robin@alldunn.com wrote:

Christopher Barker wrote:

roy zinn wrote:

I would like to implement a “ZOOM” option which should do the follow:
suppose i have image that captures the whole window and the same image in the virtual area (outside the viewable area?). when i press the zoom button, i would like to “shrink” both images in the Y axis by 1/2 so both pictures can be viewed.

any suggestion?

Use FloatCanvas – you were really close, really!

Otherwise, you’ll be re-implementing much of what’s in there…

If you decide to stick with DC’s then look at SetUserScale.


Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!


wxpython-users mailing list
wxpython-users@lists.wxwidgets.org

http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

roy zinn wrote:

As for float canvas, I'm still facing some problems with the coordinates system which is very important for my app,

Those are fixable. I was hoping to do it for you, but haven't had the time. I'll help, though.

so i'm checking new ways (but maybe i'll come back)

If you didn't want to do scaling, then I'd say you might just as well draw everything yourself. But once you add scaling, and maybe you'll want to add clicking on things, and knowing what you clicked on, and pretty son you are re-implementing much of FloatCanvas.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Hi Again,

I will try to be more specific with the application the application that i need, maybe it will be clearer which canvas to use:

  1. We have a Real Time system recording event from the CPU on a reciprocal GSM frame format. In each frame there are many events happening (there is a known list of events - about 200). These events are written to a file.

  2. We want to view those events with the application. It means that i need to draw all the GSM frame events on the chart (the number of event is not known, can be thousands). The view is as a chart, each event in a single line, and all the occurances of this event should be drawn to the app (the chart is made of frames, each frame represent time of 5000 units, each recorded event has a time stamp of start\stop time between 0-5000)

  3. After drawing the whole chart, we would like to have the ability to do things like:

a. Have Vertical “cursers” for timing computation (as in any Logic Analyzer, timeline based application)

b. Swap\Move events (e.g., move “event 1” to the place of “event 100” so it can lay side by sdie etc)

c. Filter some events

d. More actions like the above…

I guess that’s most of it,

now i need to decide which DC to use.

Thanks,

Roy.

···

On Tue, Aug 12, 2008 at 1:00 AM, Christopher Barker Chris.Barker@noaa.gov wrote:

roy zinn wrote:

As for float canvas, I’m still facing some problems with the coordinates system which is very important for my app,

Those are fixable. I was hoping to do it for you, but haven’t had the time. I’ll help, though.

so i’m checking new ways (but maybe i’ll come back)

If you didn’t want to do scaling, then I’d say you might just as well draw everything yourself. But once you add scaling, and maybe you’ll want to add clicking on things, and knowing what you clicked on, and pretty son you are re-implementing much of FloatCanvas.

-Chris


Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax

Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov


wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

roy zinn wrote:

Hi Chris, Robin,
As for float canvas, i'm still facing some problems with the coordinates system which is very important for my app, so i'm checking new ways (but maybe i'll come back)
As for SetUserScale, well, wx.PseudoDC don't have this attribute. What is the big benefit of the PseudoDC ? i started to use it because of the example in the wx docs and demos and it went well till that point.

Try using it on the target DC before you play back the operations of the PseudoDC to it.

speaking of the example, when i choose one of the items, it's sometimes on top of other items and sometime behind, is there a way to bring it to the top once selected?

PseudoDC doesn't provide a way to reorder the items in its list of operations. I think the best you can do is use ClearId to remove all items associated with the ID, and then draw them again so they end up at the end of the list.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

roy zinn wrote:

Hi Again,
I will try to be more specific with the application the application that i need, maybe it will be clearer which canvas to use:
1. We have a Real Time system recording event from the CPU on a reciprocal GSM frame format. In each frame there are many events happening (there is a known list of events - about 200). These events are written to a file.
2. We want to view those events with the application. It means that i need to draw all the GSM frame events on the chart (the number of event is not known, can be thousands). The view is as a chart, each event in a single line, and all the occurances of this event should be drawn to the app (the chart is made of frames, each frame represent time of 5000 units, each recorded event has a time stamp of start\stop time between 0-5000)
3. After drawing the whole chart, we would like to have the ability to do things like:
        a. Have Vertical "cursers" for timing computation (as in any Logic Analyzer, timeline based application)
        b. Swap\Move events (e.g., move "event 1" to the place of "event 100" so it can lay side by sdie etc)
        c. Filter some events
        d. More actions like the above...
I guess that's most of it,
now i need to decide which DC to use.

Try some task with both and see which works best for you.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Hi,

I tried to do it on the target DC but i’m not sure it’s the correct one (i put it under the OnPaint handler):

def OnPaint(self, event):
# Create a buffered paint DC. It will create the real
# wx.PaintDC and then blit the bitmap to it when dc is
# deleted.
dc = wx.BufferedPaintDC(self)

    dc.Clear()
    self.PrepareDC(dc)
    bg = wx.Brush(self.GetBackgroundColour())
    dc.SetBackground(bg)
    dc.SetUserScale(2,1)
    #dc.Clear()

   
    # create a clipping rect from our position and size
    # and the Update Region
    xv, yv = self.GetViewStart()
    dx, dy = self.GetScrollPixelsPerUnit()
    x, y   = (xv * dx, yv * dy)

    rgn = self.GetUpdateRegion()
    rgn.Offset(x,y)
    r = rgn.GetBox()
    # draw to the dc using the calculated clipping rect
    self.pdc.DrawToDCClipped(dc,r)

as for ClearId and re-draw, the Pseudo example overview states:

To re-draw an object use:
ClearId(id)
SetId(id)

and then re-draw the object.

and this is what i did (again, i am not sure that i do the redraw correct):

def OnMouse(self, event):
global hitradius
if event.LeftDown():
x,y = self.ConvertEventCoords(event)
l = self.pdc.FindObjectsByBBox(x, y)
for id in l:

            if not self.pdc.GetIdGreyedOut(id):
                r = self.pdc.GetIdBounds(id)
                x,y,w,h = r.Get()
                self.buffer = wx.EmptyBitmap(w, h)

                self.pdc.ClearId(id)
                self.pdc.SetId(id)
                dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
                dc.Clear()
                self.PrepareDC(dc)

                self.pdc.DrawIdToDC(id, dc)
                self.dragid = id
                self.lastpos = (event.GetX(),event.GetY())
                break

can you tell the problem ?

Thanks,

Roy

···

On Tue, Aug 12, 2008 at 8:44 PM, Robin Dunn robin@alldunn.com wrote:

roy zinn wrote:

Hi Chris, Robin,
As for float canvas, i’m still facing some problems with the coordinates system which is very important for my app, so i’m checking new ways (but maybe i’ll come back)

As for SetUserScale, well, wx.PseudoDC don’t have this attribute. What is the big benefit of the PseudoDC ? i started to use it because of the example in the wx docs and demos and it went well till that point.

Try using it on the target DC before you play back the operations of the PseudoDC to it.

speaking of the example, when i choose one of the items, it’s sometimes on top of other items and sometime behind, is there a way to bring it to the top once selected?

PseudoDC doesn’t provide a way to reorder the items in its list of operations. I think the best you can do is use ClearId to remove all items associated with the ID, and then draw them again so they end up at the end of the list.


Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!


wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

roy zinn wrote:

Hi,
I tried to do it on the target DC but i'm not sure it's the correct one (i put it under the OnPaint handler):

I hardly ever do scaling so I probably can't be much more help with that. All I can suggest is to do what I would do to figure out the nuances, and that is to do a methodical trial/error until you get what you want. I do have some comments below however.

def OnPaint(self, event):
        # Create a buffered paint DC. It will create the real
        # wx.PaintDC and then blit the bitmap to it when dc is
        # deleted. dc = wx.BufferedPaintDC(self)
        dc.Clear()
        self.PrepareDC(dc)
        bg = wx.Brush(self.GetBackgroundColour())
        dc.SetBackground(bg)
        dc.SetUserScale(2,1)
        #dc.Clear()
               # create a clipping rect from our position and size
        # and the Update Region
        xv, yv = self.GetViewStart()
        dx, dy = self.GetScrollPixelsPerUnit()
        x, y = (xv * dx, yv * dy)
        rgn = self.GetUpdateRegion()
        rgn.Offset(x,y)
        r = rgn.GetBox()
        # draw to the dc using the calculated clipping rect
        self.pdc.DrawToDCClipped(dc,r)
as for ClearId and re-draw, the Pseudo example overview states:
To re-draw an object use:
    ClearId(id)
    SetId(id)
and then re-draw the object.
and this is what i did (again, i am not sure that i do the redraw correct):
def OnMouse(self, event):
        global hitradius
        if event.LeftDown():
            x,y = self.ConvertEventCoords(event)
            l = self.pdc.FindObjectsByBBox(x, y)
            for id in l:
                if not self.pdc.GetIdGreyedOut(id):
                    r = self.pdc.GetIdBounds(id)
                    x,y,w,h = r.Get()
                    self.buffer = wx.EmptyBitmap(w, h)
                    self.pdc.ClearId(id)
                    self.pdc.SetId(id)
                    dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
                    dc.Clear()
                    self.PrepareDC(dc)
                    self.pdc.DrawIdToDC(id, dc)
                    self.dragid = id
                    self.lastpos = (event.GetX(),event.GetY())
                    break

I think that the way you are using the buffer bitmap here could be a problem. You are creating the bitmap the size of the object's bounds, but the wx.BufferedDC is going to assume that the buffer is covering the whole visible client area and that it is positioned at 0,0.

Since you're creating a new buffer for every iteration through the loop there is not really any reason for you to keep a reference to it. You may as well let the buffered DC make the buffer itself internally. You probably also want to move the creation of the buffered DC outside of the loop so there is only one of them per event, not one per iteration through the loop, then there would only be one flush to the client DC at the end.

One final suggestion that may or may not work well in this case is to not use a DC here at all. Just change the position of the object (or whatever is needed) and then call Refresh with the bounding box of the object(s) that need updated, and then let the actual drawing happen in the EVT_PAINT event that will be sent because of the Refresh. If you have multiple rectangles that need updated then you can call Refresh (or RefreshRect) multiple times, and they will be combined into an update region and a single EVT_PAINT event.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!