wxPython油漆损坏,裁剪区域

时间:2015-05-27 06:03:10

标签: python wxpython drawing wxwidgets

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

dispatch_group_enter

并且假设看起来如下(简单地调整框架大小)

Normal background

然而,在移动粉红色的盒子后,你会看到它真的像这样

Bad Background with ghosting

我试过以下

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

我很确定它与面板有关,因此PaintEvent只标记它部分损坏。这部分的颜色不同,使得“重影”成为焦点。或者'涂抹'明显。也许我使用了错误的词语,因为我无法找到解决方案(而且这似乎是一个非常复杂的问题,只是与“受损区域”有关。)

1 个答案:

答案 0 :(得分:0)

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

基本上,此代码的目标是移动面板,然后更新父面板。 SetPosition调用通过wxWidget代码调用DoMoveWindow的Move,所有这些都导致位置改变和重新调用调用(不确定是什么调用重绘)。大。然而,重画只标志着一个特定的区域'因为它试图提高效率。这就是为什么一些问题可以通过让专家组审视“幻影”来解决的原因。区域。你需要做的是在SetPosition之后,调用GetParent()。Refresh(),它将发送一个完整的'油漆没有任何排除区域。

另一件值得注意的事情是,有两个条款对此造成损坏'或者'剪裁'区域。一个是损害'然而,还有另一个,“肮脏的”#。损坏在wx PaintDC信息中使用

  

在EVT_PAINT处理程序中使用wx.PaintDC很重要,因为它   自动将剪裁区域设置为的损坏的区域   窗口。试图在这个区域以外的地方不会出现。

信任文档,您将大部分丢失。然而,在其中一个wxPython DoubleBuffer中,如何改变术语(但它与“伤害”相同)

  

现在是OnPaint()方法。只要是痛苦事件,它就会被召唤   由系统发送:即,当窗口的一部分时。

如果您知道Google wx Window脏了,您将获得以下内容

  

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

进行以下三个打印周期,其中在SetPosition调用后触发EVT_PAINT(这是 WITHOUT 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()