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()