关于python:wxpython – 擦除背景会擦除非背景组件

wxpython - Erase background erases non-background components

在wxpython中,我希望有一个窗口,其中包含一张根据工具栏按钮的使用而更改的图片,其中文本控件位于图片的顶部。当我单击工具栏按钮时,我将发布一个擦除背景事件,然后捕获擦除事件,并从中重新绘制新的背景(基于此)。

大多数情况下都能很好地工作,除了当我重新绘制背景时,文本控件将停止绘制。他们还在那里,只是没有画出来。

下面是一个演示问题的简化代码。如果运行此代码并单击按钮以切换是否绘制背景图像,则文本控件将消失。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import wx
import wx.lib.inspection

class PanelWithDrawing(wx.Panel):
    def __init__(self, parent):
        super(PanelWithDrawing, self).__init__(parent, size=(100, 40))

        self.showbmp = False

        self.txt = wx.TextCtrl(self, pos=(10, 10))

    def onErase(self, dc):
        if self.showbmp:
            # dc.DrawBitmap(wx.Bitmap('background.png', 0, 0)
            dc.DrawRectangle(0, 0, 40, 40)   # use a drawing instead so you don't have to find a png

class Toolbar(wx.ToolBar):
    def __init__(self, parent):
        super(Toolbar, self).__init__(parent, -1)

        self.AddLabelTool(wx.ID_SAVE,"Record", wx.Bitmap("picture.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL,"","")

class Example(wx.Frame):

    def __init__(self, parent, title):
        super(Example, self).__init__(parent, title=title)

        self.toolbar = Toolbar(self)
        self.SetToolBar(self.toolbar)
        self.toolbar.Realize()

        self.panel = wx.Panel(self)
        vbox = wx.BoxSizer(wx.VERTICAL)

        self.panel1 = PanelWithDrawing(self.panel)
        vbox.Add(self.panel1)

        # self.panel2 = PanelWithText(self.panel)
        # vbox.Add(self.panel2)

        self.panel.SetSizer(vbox)

        self.Centre()
        self.Show()

        self.toolbar.Bind(wx.EVT_TOOL, self.onButton)
        self.panel1.Bind(wx.EVT_ERASE_BACKGROUND, self.onErase)

    def onErase(self, evt):
        try:
            dc = evt.GetDC()
        except:
            dc = wx.ClientDC(self)
            rect = self.GetUpdateRegion().GetBox()
            dc.SetClippingRect(rect)
        dc.Clear()
        self.panel1.onErase(dc)

    def onButton(self, evt):
        self.panel1.showbmp = not self.panel1.showbmp
        wx.PostEvent(self.panel1, wx.PyCommandEvent(wx.wxEVT_ERASE_BACKGROUND))


if __name__ == '__main__':

    app = wx.App()
    Example(None, title='Example')
    wx.lib.inspection.InspectionTool().Show()   # use this for debugging GUI design
    app.MainLoop()

我该如何告诉wxpython重新画出所有非背景的东西?或者,我怎样才能不把它画出来呢?


在做了几天之后,我明白了!答案非常简单(和往常一样)。

应将wx.PostEvent(self.panel1, wx.PyCommandEvent(wx.wxEVT_ERASE_BACKGROUND))替换为self.Refresh()以刷新整个帧,而不仅仅强制重新绘制特定的(明显不安全的)帧。