refreshing a FloatCanvas canvas

Hello..

How can I update or refresh the canvas?

I have this code [1]. As you can see I have a variable (a list) that gets initialize like this:

self.segments = []

Later when a mouse left up event happens, that variable changes its value (Now it have a list with 2 points)

the canvas its created in the OnDraw() method, and what I want is the canvas to update itself every time the self.segments variable changes. something like the OnPaint() when your working with a DC.

I've tried with refresh(), update() and calling the OnDraw() inside the OnLeftUp() method but nothing happens..

[1] http://pastebin.com/jVxWCKhv

I don't use FC myself, but one thing you need to understand is that you need to think about it a little differently than when you are drawing things yourself. For example, instead of needing to redraw everything when something changes, you just create new or change existing objects, and the FC takes care of updating the screen. So in other words you probably don't want to be adding a new line object for every mouse button event, at least not unless you are removing the others first.

Back to your question: You are doing PixelToWorld on points that are already in world coordinates, (so the line would be outside of the visible area) but just fixing that is not quite enough. You still need to tell FC to draw the new object(s) to it's buffers so they will be displayed. Glancing at the source code turns up the Canvas.Draw() method, so adding a call to that at the end of your OnDraw seems to take care of it.

···

On 4/19/11 9:55 PM, PythonJourney wrote:

Hello..

How can I update or refresh the canvas?

I have this code [1]. As you can see I have a variable (a list) that
gets initialize like this:

self.segments =

Later when a mouse left up event happens, that variable changes its
value (Now it have a list with 2 points)

the canvas its created in the OnDraw() method, and what I want is the
canvas to update itself every time the self.segments variable changes.
something like the OnPaint() when your working with a DC.

--
Robin Dunn
Software Craftsman

thanks for answering.

El 20/04/2011 03:12 p.m., Robin Dunn escribi�:

I don't use FC myself, but one thing you need to understand is that you need to think about it a little differently than when you are drawing things yourself. For example, instead of needing to redraw everything when something changes, you just create new or change existing objects, and the FC takes care of updating the screen. So in other words you probably don't want to be adding a new line object for every mouse button event, at least not unless you are removing the others first.

But what am trying to make its precisely that. I want to draw lines with the mouse. Is not possible to do that with FC?

Back to your question: You are doing PixelToWorld on points that are already in world coordinates, (so the line would be outside of the visible area) but just fixing that is not quite enough. You still need to tell FC to draw the new object(s) to it's buffers so they will be displayed. Glancing at the source code turns up the Canvas.Draw() method, so adding a call to that at the end of your OnDraw seems to take care of it.

I believe you are talking about this:

     self.Canvas.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
     .....
     def OnLeftUp(self, evt):
         self.segments = [[[0, 0], [50, 50]]]
         Canvas = self.Canvas
         foo = evt.GetPosition()
         #print foo

first, this is what am assuming pixel coords [1] and world coords [2] are. So, if I print the coords in that method, what I get is values that resemble the pixel coords (the top left corner are (0, 0))

I put the Canvas.Draw() in the OnDraw() method, and make calls to the OnDraw() method in the OnLeftUp() to redraw the canvas with the new info and nothing happens..

[1] http://i.imgur.com/FyM7q.png
[2] http://i.imgur.com/30mzi.png

thanks for answering.

El 20/04/2011 03:12 p.m., Robin Dunn escribi�:

I don't use FC myself, but one thing you need to understand is that
you need to think about it a little differently than when you are
drawing things yourself. For example, instead of needing to redraw
everything when something changes, you just create new or change
existing objects, and the FC takes care of updating the screen. So in
other words you probably don't want to be adding a new line object for
every mouse button event, at least not unless you are removing the
others first.

But what am trying to make its precisely that. I want to draw lines with
the mouse.

Right, I guessed that from your sample. What I'm saying is that you probably do not want to create new lines for every item in the self.segments list every time you have a mouse event. Just add the new line object(s) for the new line to be drawn instead. FC will remember all of the other line objects that have already been added to the canvas.

Is not possible to do that with FC?

I'm sure it is, but it will probably take somebody more familiar with FC than I am to point you in the right direction.

Back to your question: You are doing PixelToWorld on points that are
already in world coordinates, (so the line would be outside of the
visible area) but just fixing that is not quite enough. You still need
to tell FC to draw the new object(s) to it's buffers so they will be
displayed. Glancing at the source code turns up the Canvas.Draw()
method, so adding a call to that at the end of your OnDraw seems to
take care of it.

I believe you are talking about this:

self.Canvas.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
.....
def OnLeftUp(self, evt):
self.segments = [[[0, 0], [50, 50]]]
Canvas = self.Canvas
foo = evt.GetPosition()
#print foo

first, this is what am assuming pixel coords [1] and world coords [2]
are. So, if I print the coords in that method, what I get is values that
resemble the pixel coords (the top left corner are (0, 0))

This is what I was talking about:

     def OnDraw(self):
         print 'OnDraw'
         Canvas = self.Canvas
         #Canvas.ClearAll()
         if len(self.segments) > 0:
             for segment in self.segments:
                 lineWorldCoord = [Canvas.PixelToWorld(segment[0]),
                                   Canvas.PixelToWorld(segment[1])]
You convert pixel to world coords here ^^^

                 print segment
                 print lineWorldCoord
                 Canvas.AddLine(
                           Canvas.PixelToWorld(lineWorldCoord),
                           LineColor = "Cyan")
And then do it again here ^^^

I put the Canvas.Draw() in the OnDraw() method, and make calls to the
OnDraw() method in the OnLeftUp() to redraw the canvas with the new info
and nothing happens..

See the attached. If you maximize the window after clicking (to trigger the addition of the lines) you may see the cyan line with the doubled pixel to world conversion become visible. The thick blue line is probably at the position you were expecting.

fc.py (2.79 KB)

···

On 4/20/11 8:02 PM, PythonJourney wrote:

--
Robin Dunn
Software Craftsman

Ok I get it...

Right now am drawing ALL the lines in self.segments every time I have a mouse left event, what I need to do is to draw just the new objects..

But, I would have to create a list to save the reference of those lines, so I can access them later (In case I want to delete them, etc)

Thank you very much for your help, am going to keep testing the FC library!..

El 21/04/2011 01:01 p.m., Robin Dunn escribi�:

···

On 4/20/11 8:02 PM, PythonJourney wrote:

thanks for answering.

El 20/04/2011 03:12 p.m., Robin Dunn escribi�:

I don't use FC myself, but one thing you need to understand is that
you need to think about it a little differently than when you are
drawing things yourself. For example, instead of needing to redraw
everything when something changes, you just create new or change
existing objects, and the FC takes care of updating the screen. So in
other words you probably don't want to be adding a new line object for
every mouse button event, at least not unless you are removing the
others first.

But what am trying to make its precisely that. I want to draw lines with
the mouse.

Right, I guessed that from your sample. What I'm saying is that you probably do not want to create new lines for every item in the self.segments list every time you have a mouse event. Just add the new line object(s) for the new line to be drawn instead. FC will remember all of the other line objects that have already been added to the canvas.

Is not possible to do that with FC?

I'm sure it is, but it will probably take somebody more familiar with FC than I am to point you in the right direction.

Back to your question: You are doing PixelToWorld on points that are
already in world coordinates, (so the line would be outside of the
visible area) but just fixing that is not quite enough. You still need
to tell FC to draw the new object(s) to it's buffers so they will be
displayed. Glancing at the source code turns up the Canvas.Draw()
method, so adding a call to that at the end of your OnDraw seems to
take care of it.

I believe you are talking about this:

self.Canvas.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
.....
def OnLeftUp(self, evt):
self.segments = [[[0, 0], [50, 50]]]
Canvas = self.Canvas
foo = evt.GetPosition()
#print foo

first, this is what am assuming pixel coords [1] and world coords [2]
are. So, if I print the coords in that method, what I get is values that
resemble the pixel coords (the top left corner are (0, 0))

This is what I was talking about:

    def OnDraw(self):
        print 'OnDraw'
        Canvas = self.Canvas
        #Canvas.ClearAll()
        if len(self.segments) > 0:
            for segment in self.segments:
                lineWorldCoord = [Canvas.PixelToWorld(segment[0]),
                                  Canvas.PixelToWorld(segment[1])]
You convert pixel to world coords here ^^^

                print segment
                print lineWorldCoord
                Canvas.AddLine(
                          Canvas.PixelToWorld(lineWorldCoord),
                          LineColor = "Cyan")
And then do it again here ^^^

I put the Canvas.Draw() in the OnDraw() method, and make calls to the
OnDraw() method in the OnLeftUp() to redraw the canvas with the new info
and nothing happens..

See the attached. If you maximize the window after clicking (to trigger the addition of the lines) you may see the cyan line with the doubled pixel to world conversion become visible. The thick blue line is probably at the position you were expecting.

Here [1] I put a small sample code. It adds a random line every time there's a mouse left click on the canvas...

So far so good. I want to implement more stuff to that window, so you'll probably see me later asking more questions xD..

Thanks for helping me robin!...

[1] import randomimport wxfrom wx.lib.floatcanvas import FloatCanvas as FCcl - Pastebin.com

El 21/04/2011 01:01 p.m., Robin Dunn escribi�:

···

On 4/20/11 8:02 PM, PythonJourney wrote:

thanks for answering.

El 20/04/2011 03:12 p.m., Robin Dunn escribi�:

I don't use FC myself, but one thing you need to understand is that
you need to think about it a little differently than when you are
drawing things yourself. For example, instead of needing to redraw
everything when something changes, you just create new or change
existing objects, and the FC takes care of updating the screen. So in
other words you probably don't want to be adding a new line object for
every mouse button event, at least not unless you are removing the
others first.

But what am trying to make its precisely that. I want to draw lines with
the mouse.

Right, I guessed that from your sample. What I'm saying is that you probably do not want to create new lines for every item in the self.segments list every time you have a mouse event. Just add the new line object(s) for the new line to be drawn instead. FC will remember all of the other line objects that have already been added to the canvas.

Is not possible to do that with FC?

I'm sure it is, but it will probably take somebody more familiar with FC than I am to point you in the right direction.

Back to your question: You are doing PixelToWorld on points that are
already in world coordinates, (so the line would be outside of the
visible area) but just fixing that is not quite enough. You still need
to tell FC to draw the new object(s) to it's buffers so they will be
displayed. Glancing at the source code turns up the Canvas.Draw()
method, so adding a call to that at the end of your OnDraw seems to
take care of it.

I believe you are talking about this:

self.Canvas.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
.....
def OnLeftUp(self, evt):
self.segments = [[[0, 0], [50, 50]]]
Canvas = self.Canvas
foo = evt.GetPosition()
#print foo

first, this is what am assuming pixel coords [1] and world coords [2]
are. So, if I print the coords in that method, what I get is values that
resemble the pixel coords (the top left corner are (0, 0))

This is what I was talking about:

    def OnDraw(self):
        print 'OnDraw'
        Canvas = self.Canvas
        #Canvas.ClearAll()
        if len(self.segments) > 0:
            for segment in self.segments:
                lineWorldCoord = [Canvas.PixelToWorld(segment[0]),
                                  Canvas.PixelToWorld(segment[1])]
You convert pixel to world coords here ^^^

                print segment
                print lineWorldCoord
                Canvas.AddLine(
                          Canvas.PixelToWorld(lineWorldCoord),
                          LineColor = "Cyan")
And then do it again here ^^^

I put the Canvas.Draw() in the OnDraw() method, and make calls to the
OnDraw() method in the OnLeftUp() to redraw the canvas with the new info
and nothing happens..

See the attached. If you maximize the window after clicking (to trigger the addition of the lines) you may see the cyan line with the doubled pixel to world conversion become visible. The thick blue line is probably at the position you were expecting.