0

I'm relatively new to wxpython and cairo, please forgive any beginners errors.

On drawing a rectangle with wxpython & cairo, the border (stroke) sometimes displays, and sometimes doesn't depending on the value of ctx.set_line_width(). When it does not display I get the following message in the python console (using pycharm): _cairo_win32_display_surface_flush: The operation completed successfully.

The console message appears to be generated by the .stroke() command.

If I don't check for doublebuffering, and use dc = wx.PaintDC(self) then the border appears as you would expect. However, on a complex drawing, wouldn't this cause flicking problems?

Questions:

  • On a complex drawing, is using wx.PaintDC() the right approach?
  • Is there a way of using wx.BufferedPaintDC(), with the lines showing as expected?
  • What does the console message mean? ("_cairo_win32_display_surface_flush: The operation completed successfully")

I'm very confused by this, so any help will be appreciated.

Coding with Python 3.8, wxpython 4.1 and cairo (cairocffi) on Windows.

My paint event code is:

    def on_paint(self, event):

        if self.IsDoubleBuffered():
            dc = wx.PaintDC(self)
        else:
            dc = wx.BufferedPaintDC(self)

        dc.SetBackground(wx.WHITE_BRUSH)
        dc.Clear()

        w, h = self.GetClientSize()
        ctx = wxcairo.ContextFromDC(dc)

        # draw stuff
        ctx.set_source_rgb(0.65, 0.65, 0.65)
        ctx.rectangle(25, 25, w-50, h-50)
        ctx.fill_preserve()
        ctx.set_source_rgb(0.1, 0.1, 0.1)
        ctx.set_line_width(1)  # width of 10 works, width of 1 doesn't
        ctx.stroke()

Simplified demonstration code:

import wx
import wx.lib.wxcairo as wxcairo


class MyPanel(wx.Panel):
    def __init__(self, parent, *args, **kwargs):
        super(MyPanel, self).__init__(parent, *args, **kwargs)

        self.Bind(wx.EVT_SIZE, self.on_resize)
        self.Bind(wx.EVT_PAINT, self.on_paint)
        self.Bind(wx.EVT_ERASE_BACKGROUND, self.on_erase_bkground)

    def on_erase_bkground(self, event):
        pass

    def on_resize(self, event):
        self.Refresh()
        self.Layout()

    def on_paint(self, event):

        if self.IsDoubleBuffered():  # returns false
            dc = wx.PaintDC(self)
        else:
            dc = wx.BufferedPaintDC(self)

        # dc = wx.PaintDC(self)  # works as anticipated with thin line widths
        dc.SetBackground(wx.WHITE_BRUSH)
        dc.Clear()

        w, h = self.GetClientSize()
        ctx = wxcairo.ContextFromDC(dc)

        # draw stuff
        ctx.set_source_rgb(0.65, 0.65, 0.65)
        ctx.rectangle(25, 25, w-50, h-50)
        ctx.fill_preserve()
        ctx.set_source_rgb(0.1, 0.1, 0.1)
        ctx.set_line_width(1)  # width of 10 works, width of 1 doesn't
        ctx.stroke()  # console message generated by this line

class MyFrame(wx.Frame):
    def __init__(self, parent, title):
        super(MyFrame, self).__init__(None, title=title, size=(600, 400))

        # simple layout
        panel = MyPanel(self)
        sizer = wx.BoxSizer()
        sizer.Add(panel, 1, wx.EXPAND)
        self.SetSizer(sizer)

        # display
        self.Center()
        self.Show()


if __name__ == '__main__':
    app = wx.App()
    frame = MyFrame(None, 'WXPython demo')
    app.MainLoop()
alex
  • 3
  • 2
  • 'What does the console message mean? ("_cairo_win32_display_surface_flush: The operation completed successfully")' It means that something went wrong. `_cairo_win32_display_surface_flush` is a function in cairo's source code. This function has two places where it checks if it successfully copied something and if not, it prints the error (as seen by the Windows API `GetLastError()`). That error seems to be "there was no error", which makes no sense to me. – Uli Schlachter Sep 16 '20 at 13:46
  • Thank you, appreciate that you replied. – alex Sep 21 '20 at 20:25

0 Answers0