Lag initialising a wx.Overlay

I'm creating a drawing program, and am using a wx,Overlay to produce rubber band drawing for ellipses/circles/rectangles etc.

My drawing code for the Rectangle is as follows:

draw is called with replay as False, as using True is used when render all the currently drawn shapes

def draw(self, dc, replay=True):
    dc.SetPen(self.pen)
    dc.SetBrush(wx.TRANSPARENT_BRUSH)

    if not replay:
        self.draw_outline(dc)
    dc.DrawRectangle(self.x, self.y.....

def draw_outline(self, dc):
    odc = wx.DCOverlay(self.board.overlay, dc)
    odc.Clear()

def button_up(self, x, y):
    """
    Clears the created overlay for rubber banding.
    """
    dc = wx.ClientDC(self.board)
    odc = wx.DCOverlay(self.board.overlay, dc)
    odc.Clear()
    self.board.overlay.Reset()
    self.board.Refresh() # show self on whyteboard

Now, on my machine, Ubuntu 8.10, Nvidia 8800GT / 180.27 drivers, AMD X2-3800, 2.5GHz, 2GB low-latency DDR RAM my application runs fine. I click the button which creates an object for drawing an ellipse, left click in my drawing panel to begin the drawing and it renders instantly.

On the machines in university, Ubuntu 8.04, Nvidia 8600GT / Intel Quad core, 2.6GHz, 3GB RAM ..but I'm pretty sure there's no graphics drivers, drawing freestyle, with a pen runs smoothly, no issues there.

However, when drawing a rubber band shape like a circle or rectangle, there is a noticeable second or more lag from pressing the left mouse button and holding it, moving the mouse and the rectangle appearing on screen. If I do this like twice then it seems to snap out of the lag, and work as smoothly as on my machine. Changing shapes then, say rectangle-> circle then causes the same lag when trying to draw initially

it also seems to happen if you left click, hold down the mouse and try and drag out the outline in all directions, after 3 seconds of lag and maybe one screen update every second, the lag wears off and you can drag the outline great.

http://bazaar.launchpad.net/~sproaty/whyteboard/development/files - grab the complete code from here; of interest is whyteboard.py for the panel which can be drawn upon, and the Rectangle class in tools.py - all the other 'rubber band' classes extend from Rectangle

Thanks for your time,
Steven Sproat

Steven Sproat wrote:

I'm creating a drawing program, and am using a wx,Overlay to produce rubber band drawing for ellipses/circles/rectangles etc.

When I messed around with wx.Overlay, I could never really get it to perform reliably for this kind of thing, either.

I've stuck with plain old wx.ClientDC drawing. YOU can see how it can be done in the RubberBandBox class in:

wx.lib.floatcannvas.Utilities.GUI

Which brings me to:

Have you looked at existing code to build your drawing program on? It's a shame to re-invent the wheel.

wx.lib.floatcanvas is one, or FloatCanvas2, which is in SVN now:

http://svn.wxwidgets.org/viewvc/wx/wxPython/3rdParty/branches/FloatCanvas/SOC2008_FloatCanvas/floatcanvas2/

It's not already a drawing program, but has much of the infrastructure to build one.

-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

Christopher Barker wrote:

Steven Sproat wrote:

I'm creating a drawing program, and am using a wx,Overlay to produce rubber band drawing for ellipses/circles/rectangles etc.

When I messed around with wx.Overlay, I could never really get it to perform reliably for this kind of thing, either.

I've stuck with plain old wx.ClientDC drawing. YOU can see how it can be done in the RubberBandBox class in:

wx.lib.floatcannvas.Utilities.GUI

The overlay runs fine on my machine, and my university lecturer's machine too, however on the machines with no graphic drivers there was issues. Perhaps it was trying to initialise the overlay and has to use a large amount of CPU resources.

Which brings me to:

Have you looked at existing code to build your drawing program on? It's a shame to re-invent the wheel.

wx.lib.floatcanvas is one, or FloatCanvas2, which is in SVN now:

http://svn.wxwidgets.org/viewvc/wx/wxPython/3rdParty/branches/FloatCanvas/SOC2008_FloatCanvas/floatcanvas2/

It's not already a drawing program, but has much of the infrastructure to build one.

-Chris

It's only a few days back I downloded the 2.8.9 demos for wx, I'd had the 2.6 versions installed for ages, which I did use to build my app. upon. I was thinking about floatcanvas, but haven't looked into it much, the zooming/panning and selection making/moving would be rather useful to inherit and build upon

I'm having a good learning experience just playing around with stuff myself, I've got a decent system architecture to my program now which should make it easier for me to build upon. I'm deciding if I even need the float canvas, zooming would be the most useful but I might try and implement my own version or something, it's probably stupidly hard though

Thanks for the reply,
Steven Sproat

Steven Sproat wrote:

Now, on my machine, Ubuntu 8.10, Nvidia 8800GT / 180.27 drivers, AMD X2-3800, 2.5GHz, 2GB low-latency DDR RAM my application runs fine. I click the button which creates an object for drawing an ellipse, left click in my drawing panel to begin the drawing and it renders instantly.

On the machines in university, Ubuntu 8.04, Nvidia 8600GT / Intel Quad core, 2.6GHz, 3GB RAM ..but I'm pretty sure there's no graphics drivers, drawing freestyle, with a pen runs smoothly, no issues there.

However, when drawing a rubber band shape like a circle or rectangle, there is a noticeable second or more lag from pressing the left mouse button and holding it, moving the mouse and the rectangle appearing on screen. If I do this like twice then it seems to snap out of the lag, and work as smoothly as on my machine. Changing shapes then, say rectangle-> circle then causes the same lag when trying to draw initially

Are the university machines running the application on the local display or is it a networked X-Server type of environment? X-Windows totally separates the application and the display, keyboard and mouse input of the application. Putting a network link in the middle instead of a local unix socket, named pipe and/or shared memory can sometimes introduce lags like you are seeing as complex things do require a lot of communication over that link.

it also seems to happen if you left click, hold down the mouse and try and drag out the outline in all directions, after 3 seconds of lag and maybe one screen update every second, the lag wears off and you can drag the outline great.

~sproaty/whyteboard/development : files for revision 451 - grab the complete code from here; of interest is whyteboard.py for the panel which can be drawn upon, and the Rectangle class in tools.py - all the other 'rubber band' classes extend from Rectangle

If you can produce a small sample app that just shows the problem then I would like to take a look at it.

http://wiki.wxpython.org/MakingSampleApps

···

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

Steven Sproat wrote:

I'm having a good learning experience just playing around with stuff myself,

Always true, but you can learn a lot from other folk's code too.

I'm deciding if I even need the float canvas, zooming would be the most useful but I might try and implement my own version or something, it's probably stupidly hard though

well, there are a lot of details -- anyway, I'm trying to save you work, but more important, trying to get someone else to contribute to 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

Robin Dunn wrote:

However, when drawing a rubber band shape like a circle or rectangle, there is a noticeable second or more lag from pressing the left mouse button and holding it, moving the mouse and the rectangle appearing on screen. If I do this like twice then it seems to snap out of the lag, and work as smoothly as on my machine. Changing shapes then, say rectangle-> circle then causes the same lag when trying to draw initially

Are the university machines running the application on the local display or is it a networked X-Server type of environment? X-Windows totally separates the application and the display, keyboard and mouse input of the application. Putting a network link in the middle instead of a local unix socket, named pipe and/or shared memory can sometimes introduce lags like you are seeing as complex things do require a lot of communication over that link.

Ah, I never thought of this. To be honest, I have no idea what's going on, however there are some weirdness with the machines, for example minimising any application will bring in visual lag of like, 3 outlines of rectangles, getting progressively small as the minimised window gets resized to show the effect of minimising it

If you can produce a small sample app that just shows the problem then I would like to take a look at it.

http://wiki.wxpython.org/MakingSampleApps

Sure thing: http://pastebin.com/f5cb646c3

or, here's the code:

#!/usr/bin/python

import wx

···

#----------------------------------------------------------------------

class Drawing(wx.ScrolledWindow):
    """
    The drawing frame of the application.
    """

    def __init__(self, parent):
        """
        Initalise the window, class variables and bind mouse/paint events
        """
        wx.ScrolledWindow.__init__(self, parent)
        self.virtual_size = (1280, 1024)
        self.SetVirtualSize(self.virtual_size)
        self.SetScrollRate(20, 20)
        self.SetBackgroundColour("White")

        self.overlay = wx.Overlay() # drawing "rubber bands"
        self.drawing = False

        self.width = 0
        self.height = 0
        self.x = 0
        self.y = 0

        self.buffer = wx.EmptyBitmap(*self.virtual_size)
        dc = wx.BufferedDC(None, self.buffer)
        dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
        dc.Clear()

        self.Bind(wx.EVT_LEFT_DOWN, self.left_down)
        self.Bind(wx.EVT_LEFT_UP, self.left_up)
        self.Bind(wx.EVT_MOTION, self.left_motion)
        self.Bind(wx.EVT_PAINT, self.on_paint)

    def convert_coords(self, event):
        """
        Translate mouse x/y coords to virtual scroll ones.
        """
        newpos = self.CalcUnscrolledPosition(event.GetX(), event.GetY())
        return newpos

    def left_down(self, event):
        """
        Called when the left mouse button is pressed
        Either begins drawing, starts the drawing motion or ends drawing.
        """
        x, y = self.convert_coords(event)
        self.x = x
        self.y = y
        self.drawing = True

    def left_motion(self, event):
        """
        Called when the mouse is in motion.
        """
        if self.drawing:
            x, y = self.convert_coords(event)
            self.width = x - self.x
            self.height = y - self.y

            dc = wx.BufferedDC(None, self.buffer)
            dc.SetPen(wx.Pen("Red", 3, wx.SOLID))
            dc.SetBrush(wx.TRANSPARENT_BRUSH)

            odc = wx.DCOverlay(self.overlay, dc)
            odc.Clear()
            dc.DrawRectangle(self.x, self.y, self.width, self.height)
            self.Refresh()

    def left_up(self, event):
        """
        Called when the left mouse button is released.
        """
        if self.drawing:
            self.x, self.y, self.width, self.height = 0, 0, 0, 0

            dc = wx.ClientDC(self)
            odc = wx.DCOverlay(self.overlay, dc)
            odc.Clear()
            self.overlay.Reset()
            self.Refresh()

            self.drawing = False

    def on_paint(self, event):
        """
        Called when the window is exposed.
        """
        wx.BufferedPaintDC(self, self.buffer, wx.BUFFER_VIRTUAL_AREA)

#----------------------------------------------------------------------

class TestFrame(wx.Frame):

    def __init__(self, parent):
        """
        Initialise utility, status/menu/tool bar, tabs, ctrl panel + bindings.
        """
        wx.Frame.__init__(self, parent, size=(800, 600),
                    style=wx.DEFAULT_FRAME_STYLE | wx.FULL_REPAINT_ON_RESIZE)
        self.drawing = Drawing(self)

class TestApp(wx.App):
    def OnInit(self):
        frame = TestFrame(None)
        frame.Show(True)
        return True

#----------------------------------------------------------------------

if __name__ == '__main__':
    app = TestApp()
    app.MainLoop()

wow, that was mad stripping my application down to that code, it seems like I have so much extra stuff there :slight_smile:
Thanks for the help, Robin and Christopher

regards,
Steven Sproat

Robin Dunn wrote:

Are the university machines running the application on the local display or is it a networked X-Server type of environment? X-Windows totally separates the application and the display, keyboard and mouse input of the application. Putting a network link in the middle instead of a local unix socket, named pipe and/or shared memory can sometimes introduce lags like you are seeing as complex things do require a lot of communication over that link.

Hi, sorry for the double reply to this thread, I just received some details about how the university's Linux environment in configured: all university clients are running X locally, on 64-bit machines. I forgot to test the application with compiz enabled, as the "rectangle outline of the application as it's being minimised" issue I mentioned in the last e-mail doesn't happen with compiz enabled.

thanks,
Steven Sproat

Steven Sproat wrote:

Robin Dunn wrote:

However, when drawing a rubber band shape like a circle or rectangle, there is a noticeable second or more lag from pressing the left mouse button and holding it, moving the mouse and the rectangle appearing on screen. If I do this like twice then it seems to snap out of the lag, and work as smoothly as on my machine. Changing shapes then, say rectangle-> circle then causes the same lag when trying to draw initially

Are the university machines running the application on the local display or is it a networked X-Server type of environment? X-Windows totally separates the application and the display, keyboard and mouse input of the application. Putting a network link in the middle instead of a local unix socket, named pipe and/or shared memory can sometimes introduce lags like you are seeing as complex things do require a lot of communication over that link.

Ah, I never thought of this. To be honest, I have no idea what's going on, however there are some weirdness with the machines, for example minimising any application will bring in visual lag of like, 3 outlines of rectangles, getting progressively small as the minimised window gets resized to show the effect of minimising it

If you can produce a small sample app that just shows the problem then I would like to take a look at it.

[...]

wow, that was mad stripping my application down to that code, it seems like I have so much extra stuff there :slight_smile:

I don't know if it has anything to do with the lag, but there are a couple things I would change. First, you must delete the odc before resetting the overlay. Second you are Refreshing more than is needed. Third, I would use a plain wx.ClientDC in left_motion instead of a buffered DC. The overlay should take care of buffering there.

overlay.py (3.38 KB)

···

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