Double buffered scrolled window failing in wxPython 2.9.3.1.

Hi,

Would someone be able to see what I am doing wrong here? The minimal
code at the bottom is for a double buffered scrolled window. The code
works fine with wxPython 2.8, but fails terribly in 2.9.3.1 - the dc
is drawn to the original size of the window and not to the virtual
size. This problem is independent of wxGTK, wxMSW, and wxMac.
Cheers!

Edward

import wx

class Test(wx.Frame):
    """The about dialog base class."""

    # Dimensions.
    dim_x = 800
    dim_y = 800
    virt_x = 800
    virt_y = 2500

    def __init__(self, parent=None, id=-1, title='', html_text=None):
        """Build the dialog."""

        # Execute the base class __init__() method.
        super(Test, self).__init__(parent=parent, id=id, title=title,
style=wx.DEFAULT_FRAME_STYLE)

        # Create a scrolled window.
        self.window = wx.ScrolledWindow(self, -1)

        # Set the window size.
        self.SetSize((self.virt_x, self.dim_y))

        # Set the window virtual size.
        self.window.SetVirtualSize((self.virt_x, self.virt_y))

        # Add y scrolling.
        self.window.SetScrollRate(0, 20)

        # Create the buffered device context.
        self.create_buffered_dc()

        # Bind events.
        self.window.Bind(wx.EVT_PAINT, self.on_paint)
        self.window.Bind(wx.EVT_SCROLLWIN, self.on_scroll)

    def create_buffered_dc(self):
        """Build the buffered dc containing the window contents."""

        # The buffer for buffered drawing (work around for a GTK bug,
the bitmap must be square!!!).
        size = max(self.virt_x, self.virt_y)
        self.buffer = wx.EmptyBitmap(size, size)

        # Create the device context.
        self.dc = wx.BufferedDC(None, self.buffer)

        # Set a background.
        self.dc.GradientFillLinear((0, 0, self.virt_x, self.virt_y),
'#e5feff', '#88cbff', wx.SOUTH)

        # Cross.
        self.dc.DrawLine(0, 0, self.virt_x, self.virt_y)
        self.dc.DrawLine(self.virt_x, 0, 0, self.virt_y)

        # Lines every 200 pixels.
        num = self.virt_y / 200
        for i in range(num+1):
            pos = i * 200
            self.dc.DrawLine(0, pos, self.virt_x, pos)
            self.dc.SetFont(wx.Font(8, wx.FONTFAMILY_SCRIPT,
wx.NORMAL, wx.NORMAL))
            self.dc.DrawText(str(pos), self.virt_x-40, pos-10)

        # Finish.
        self.dc.EndDrawing()

    def on_paint(self, event):
        """Build the device context, add the background, and build the dialog.

        @param event: The wx event.
        @type event: wx event
        """

        # Create the device context.
        wx.BufferedPaintDC(self.window, self.buffer, wx.BUFFER_VIRTUAL_AREA)

    def on_scroll(self, event):
        """Build the device context, add the background, and build the dialog.

        @param event: The wx event.
        @type event: wx event
        """

        print "Scrolling"
        self.window.PostSizeEvent()
        event.Skip()

if __name__ == "__main__":
    app = wx.App()
    win = Test()
    app.SetTopWindow(win)
    win.Show()
    app.MainLoop()

I don't see right off what is causing the problem, but you can use the following code as a workaround in your on_paint:

         dc = wx.PaintDC(self.window)
         self.window.PrepareDC(dc)
         dc.DrawBitmap(self.buffer, 0,0)

It does the same thing that wx.BufferedPaintDC should be doing.

···

On 4/24/12 8:44 AM, Edward d'Auvergne wrote:

Hi,

Would someone be able to see what I am doing wrong here? The minimal
code at the bottom is for a double buffered scrolled window. The code
works fine with wxPython 2.8, but fails terribly in 2.9.3.1 - the dc
is drawn to the original size of the window and not to the virtual
size. This problem is independent of wxGTK, wxMSW, and wxMac.
Cheers!

--
Robin Dunn
Software Craftsman

Hi

The workaround works perfectly. I wonder what is wrong with
wx.BufferedPaintDC?

Cheers!

Edward

···

On Apr 24, 7:12 pm, Robin Dunn <ro...@alldunn.com> wrote:

On 4/24/12 8:44 AM, Edward d'Auvergne wrote:

> Hi,

> Would someone be able to see what I am doing wrong here? The minimal
> code at the bottom is for a double buffered scrolled window. The code
> works fine with wxPython 2.8, but fails terribly in 2.9.3.1 - the dc
> is drawn to the original size of the window and not to the virtual
> size. This problem is independent of wxGTK, wxMSW, and wxMac.
> Cheers!

I don't see right off what is causing the problem, but you can use the
following code as a workaround in your on_paint:

     dc = wx\.PaintDC\(self\.window\)
     self\.window\.PrepareDC\(dc\)
     dc\.DrawBitmap\(self\.buffer, 0,0\)

It does the same thing that wx.BufferedPaintDC should be doing.

--
Robin Dunn
Software Craftsmanhttp://wxPython.org

     dc = wx\.PaintDC\(self\.window\)
     self\.window\.PrepareDC\(dc\)
     dc\.DrawBitmap\(self\.buffer, 0,0\)

It does the same thing that wx.BufferedPaintDC should be doing.
Robin Dunn

Oddly that code didn't work in wxPython 2.8.12
  # Create the device context.
  if False:
    # works
    wx.BufferedPaintDC(self.window, self.buffer,
wx.BUFFER_VIRTUAL_AREA)
  else:
    # no worky
    dc = wx.PaintDC(self.window)
    self.window.PrepareDC(dc)
    dc.DrawBitmap(self.buffer, 0,0)

Actually, I found that this solution worked for Mac OS X and Linux, but on MS Windows with both 2.8 and 2.9 the DC was completely grey! My current solution for all operating systems is:

    # Temporary fix for wxPython 2.9.3.1 suggested by Robin Dunn at http://groups.google.com/group/wxpython-users/browse_thread/thread/7dff3f5d7ca24985.
    dc = wx.PaintDC(self.window)
    self.window.PrepareDC(dc)
    dc.DrawBitmap(self.buffer, 0, 0)

    # Create the device context.
    wx.BufferedPaintDC(self.window, self.buffer, wx.BUFFER_VIRTUAL_AREA)

This temp solution appears to work on all 3 OSs with both stable and developmental wxPython.

Regards,

Edward

···

On Wednesday, 25 April 2012 21:59:21 UTC+2, DevPlayer wrote:

     dc = wx.PaintDC(self.window)
     self.window.PrepareDC(dc)
     dc.DrawBitmap(self.buffer, 0,0)

It does the same thing that wx.BufferedPaintDC should be doing.

Robin Dunn

Oddly that code didn’t work in wxPython 2.8.12

    # Create the device context.

    if False:

            # works

            wx.BufferedPaintDC(self.window, self.buffer,

wx.BUFFER_VIRTUAL_AREA)

    else:

            # no worky

            dc = wx.PaintDC(self.window)

            self.window.PrepareDC(dc)

            dc.DrawBitmap(self.buffer, 0,0)

Weird. You really should not need to do both. Other than the clipping issue in wx.BufferedPaintDC they are doing basically the same thing. In fact I halfway expected that creating more than one paint dc in the same paint event would cause a problem on Windows. If you want to keep both then I would make it conditional on "wx.VERISON > (2,9) and wx.VERSION < (2,9,4)".

···

On 6/14/12 1:57 AM, Edward d'Auvergne wrote:

Actually, I found that this solution worked for Mac OS X and Linux, but
on MS Windows with both 2.8 and 2.9 the DC was completely grey! My
current solution for all operating systems is:

# Temporary fix for wxPython 2.9.3.1 suggested by Robin Dunn at
http://groups.google.com/group/wxpython-users/browse_thread/thread/7dff3f5d7ca24985.
dc = wx.PaintDC(self.window)
self.window.PrepareDC(dc)
dc.DrawBitmap(self.buffer, 0, 0)

# Create the device context.
wx.BufferedPaintDC(self.window, self.buffer, wx.BUFFER_VIRTUAL_AREA)

This temp solution appears to work on all 3 OSs with both stable and
developmental wxPython.

--
Robin Dunn
Software Craftsman