【问题标题】:wxPython Paint Damaged, Clipped areawxPython 油漆损坏,裁剪区域
【发布时间】:2015-05-27 06:03:09
【问题描述】:

我有以下简单的代码(单击粉红色的框,您可以在按住鼠标左键的同时用鼠标移动它)。

import wx


class AppPanel(wx.Panel):

    def __init__(self, parent, id):
        wx.Panel.__init__(self, parent, id)
        p = MovablePanel(self, -1)
        self.i = 0
        self.Bind(wx.EVT_PAINT, self.OnPaint, self)

    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        self.i = self.i+10
        c = self.i % 255
        c = (0, 0, c)
        dc.SetPen(wx.Pen(c))
        dc.SetBrush(wx.Brush(c))
        dc.DrawRectangle(0, 0, 10000,10000)





class MovablePanel(wx.Panel):

    def __init__(self, parent, id):
        wx.Panel.__init__(self, parent, id)
        self.SetMinSize((500,500))
        self.SetSize((500,500))
        self.SetBackgroundColour("PINK")
        self.LEFT_DOWN = False
        self.Bind(wx.EVT_MOTION, self.OnMove, self)

        self.Bind(wx.EVT_LEFT_DOWN,
                         self.OnClickDown,
                         self)


        self.Bind(wx.EVT_LEFT_UP,
                         self.OnClickUp,
                         self)

    def OnClickUp(self, event):
        self.LEFT_DOWN = False
        self.Refresh()

    def OnClickDown(self, event):    
        self.LEFT_DOWN = True
        self.Refresh()

    def OnMove(self, event):
        if self.LEFT_DOWN:
            p = self.GetTopLevelParent().ScreenToClient(wx.GetMousePosition())
            self.SetPosition(p)


if __name__ == "__main__":
    app = wx.App(False)
    f   = wx.Frame(None, -1, size = (700, 700))
    p   = AppPanel(f, -1)
    f.Show()
    f.Maximize()
    app.MainLoop()

假设如下所示(只需调整框架大小)

但是在移动粉红色的盒子之后你会看到它真的看起来像这样

我已经尝试了以下

dc.Clear()

dc.DestroyClippingRegion() 

wx.FULL_REPAINT_ON_RESIZE

wx.EVT_ERASE_BACKGROUND

我很确定这与它是一个面板有关,因此 PaintEvent 仅将其标记为部分损坏。这部分的颜色不同,使“重影”或“拖尾”明显。也许我用错了词,因为我找不到解决方案(我这似乎是一个不复杂的问题,只是与“受损”区域有关)。

【问题讨论】:

    标签: python wxpython drawing wxwidgets


    【解决方案1】:

    好的,我发现了问题,但稍后我会尝试发布更多详细信息。

    基本上,这段代码的目标是移动一个面板,然后更新父面板。 SetPosition 调用Move,它通过wxWidget 代码调用DoMoveWindow,所有这些都会导致位置变化和重绘调用(还不确定是什么调用重绘)。伟大的。然而,重绘只标记了某个“区域”,因为它试图提高效率。这就是为什么可以通过让面板越过“幻影”区域来解决某些问题的原因。您要做的是在 SetPosition 之后调用 GetParent().Refresh(),它将发送一个没有任何排除区域的“完整”绘制。

    另外需要注意的是,这个“损坏”或“剪断”区域有两个术语。一个是“损坏”,但还有另一个是“脏”。 wx PaintDC信息中使用了伤害

    在 EVT_PAINT 处理程序中使用 wx.PaintDC 很重要,因为它 自动将剪辑区域设置为损坏区域 窗户。不会出现在此区域之外绘制的尝试。

    相信文档会让您迷失方向。然而,在其中一个 wxPython DoubleBuffer 中,术语如何变化(但它与“损坏”相同)

    现在是 OnPaint() 方法。每当发生疼痛事件时都会调用它 由系统发送:即每当窗口的一部分变得

    知道这一点,如果你 Google wx Window 脏了,你会得到以下信息

    标记指定的矩形(或整个窗口)为“脏”所以它 将被重新粉刷。导致生成并发送 EVT_PAINT 事件 到窗口。

    在以下三个打印周期中,在 SetPosition 调用后触发了 EVT_PAINT(这是没有 GetParent().Refresh() 调用)

    # first EVT_PAINT
    Drawing
    Panel Size (1440, 851)
    Clipping Rect (0, 0, 1440, 851)
    Client Update Rect (x=0, y=6, w=500, h=501) # the only place getting update is 
                                                # directly below the panel 
                                                # (that is (500, 500) )
    
    # second
    Drawing
    Panel Size (1440, 851)
    Clipping Rect (0, 0, 1440, 851)
    Client Update Rect (x=0, y=6, w=910, h=845) # however this time the update area is                                                                                                                            
                                                # bigger, this is also right before
                                                # the move
                                                # i believe what it is doing is
                                                # drawing from (0,6) to (910, 851)
                                                # why? because the panel is moving to
                                                # (410, 390) and the bottom right
                                                # corner of the panel (after moved)
                                                # is (410+500, 390+461) = (910, 851)
                                                # or about where the edge of the panel
                                                # will be
    
    # third
    Drawing
    Panel Size (1440, 851)
    Clipping Rect (0, 0, 1440, 851)
    Client Update Rect (x=410, y=390, w=500, h=461)
    

    这是可以玩的更新代码,希望这对其他人有帮助。

    import wx
    
    instructions = """
    How to use.
    1) Hover your mouse over the pink panel.
    2) Click down (left click)
    3) While holding down drag mouse around
    4) Release mouse button to stop.
    
    """
    
    class AppPanel(wx.Panel):
    
        def __init__(self, parent, id):
            wx.Panel.__init__(self, parent, id)
            self.sizer = wx.BoxSizer(wx.VERTICAL)
            self.settings_sizer = wx.BoxSizer(wx.HORIZONTAL)
            p = MovablePanel(self, -1)
    
            self.c = wx.CheckBox(self, -1, label = "Ghosting On?")
            self.p = p
            self.i = 0
    
            self.settings_sizer.Add(self.c)
    
            self.sizer.Add(self.settings_sizer)
            self.sizer.Add(self.p)
            self.SetSizer(self.sizer)
            self.Layout()
    
            self.Bind(wx.EVT_CHECKBOX, self.OnCheck, self.c)
            self.Bind(wx.EVT_PAINT, self.OnPaint, self)
            self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnErase, self)
    
    
        def OnCheck(self, event):
            print "CHECK\n\n\n\n\n"
            v = self.c.GetValue()
            self.p.r = v
            print v
    
    
        def OnErase(self, event):
            pass
    
        def OnPaint(self, event):
            print "Drawing"
            dc = wx.PaintDC(self)
            print "Panel Rect, ", self.p.GetPosition(),
            print self.p.GetSize()
            print "Clipping Rect", dc.GetClippingBox()
            print "Client Update Rect", self.GetUpdateClientRect()
            print "----------------------------"
            self.i = self.i+10
            c = self.i % 255
            c = (0, 0, c)
            dc.SetPen(wx.Pen(c))
            dc.SetBrush(wx.Brush(c))
    
            dc.DrawRectangle(0, 0, 10000,10000)
            self.SetBackgroundColour(c)
    
            dc.SetPen(wx.Pen("WHITE"))
            dc.SetBrush(wx.Brush("WHITE"))
    
    
            dc.DrawRectangle(0, 0, self.GetSize()[0], self.c.GetSize()[1])
    
    
    
    
    
    class MovablePanel(wx.Panel):
    
        def __init__(self, parent, id):
            wx.Panel.__init__(self, parent, id)
            self.SetMinSize((300,300))
            self.SetSize((300,300))
    
            txt = wx.StaticText(self, -1, label = "CLICK AND DRAG ME!")
            inst = wx.StaticText(self, -1, label = instructions)
    
            font = wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD)
            txt.SetFont(font)
            inst.SetFont(font)
    
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(txt, flag = wx.ALIGN_CENTRE_VERTICAL | wx.ALIGN_CENTRE_HORIZONTAL)
            sizer.Add(inst, flag = wx.ALIGN_CENTRE_VERTICAL | wx.ALIGN_CENTRE_HORIZONTAL)
            self.SetSizer(sizer)
    
            self.SetBackgroundColour("PINK")
            self.LEFT_DOWN = False
            self.r = False
            self.Bind(wx.EVT_MOTION, self.OnMove, self)
    
            self.Bind(wx.EVT_LEFT_DOWN,
                             self.OnClickDown,
                             self)
    
    
            self.Bind(wx.EVT_LEFT_UP,
                             self.OnClickUp,
                             self)
    
        def OnClickUp(self, event):
            self.LEFT_DOWN = False
            self.Refresh()
    
        def OnClickDown(self, event):    
            self.LEFT_DOWN = True
            self.Refresh()
    
        def OnMove(self, event):
            if self.LEFT_DOWN:
                p = self.GetTopLevelParent().ScreenToClient(wx.GetMousePosition())
                self.SetPosition(p)
                if not self.r:
                    self.GetParent().Refresh()
    
    
    if __name__ == "__main__":
        app = wx.App(False)
        f   = wx.Frame(None, -1, size = (700, 700))
        p   = AppPanel(f, -1)
        f.Show()
        app.MainLoop()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-12
      • 1970-01-01
      • 2018-06-18
      • 2013-08-11
      • 2015-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多