首页 > 解决方案 > 用 wxpython cairo 绘图感到困惑;wx.BufferedPaintDC 使笔触消失

问题描述

我对 wxpython 和 cairo 比较陌生,请原谅任何初学者的错误。

在使用 wxpython 和 cairo 绘制矩形时,有时会显示边框(笔划),有时不取决于ctx.set_line_width(). 当它不显示时,我在 python 控制台(使用 pycharm)中收到以下消息: _cairo_win32_display_surface_flush:操作成功完成。

控制台消息似乎是由 .stroke() 命令生成的。

如果我不检查双缓冲并使用,dc = wx.PaintDC(self)那么边框会如您所料那样出现。但是,在复杂的绘图上,这不会导致闪烁问题吗?

问题:

我对此感到非常困惑,因此将不胜感激。

在 Windows 上使用 Python 3.8、wxpython 4.1 和 cairo (cairocffi) 进行编码。

我的绘画事件代码是:

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

简化的演示代码:

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

标签: wxpythoncairodouble-buffering

解决方案


推荐阅读