Dialog的ShowModal()不会发送EVT_PAINT

时间:2015-02-17 21:39:43

标签: python-2.7 events dialog wxpython

wx版本:2.8.12.1

我正在尝试构建一个已设置的对话框(背景,按钮,位图边框等),但在ShowModal()上不会发出Paint事件。

适用于Show()超级种子wx.PopupTransientWindow,但不适用Show()上的ShowModal()wx.Dialog

如果您运行该示例,请打开对话框,然后单击两个按钮之一,您将进入终端:

send refresh
Clicked OK/CANCEL

"Paint Event""Draw Function"无法打印。 "send refresh"表示已发出手册Refresh();那应该发出wx.EVT_PAINT

如果OnPaint绑定到wx.EVT_SHOW,系统会调用这些功能,wx.BufferedPaintDC将被正确设置,但它不会更改任何可见的内容。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx

def GetThemeTools(borderWidth, backgrounColour):
    return {
        'Pens': {
            'DarkRectSolidBorder': wx.Pen( wx.Colour(67, 67, 67), borderWidth),
        },
        'Brushes': {
            'Background': wx.Brush(backgrounColour),
            'RectBoxFilling': wx.Brush( wx.Colour(119,120,119) ),
        },
        'ForegroundColor': wx.Colour(241,241,241),
        'BackgroundColor': 'WHITE',
        'Fonts': {
            'Brief': wx.Font(  pointSize=12, 
                                family=wx.FONTFAMILY_SWISS,
                                style=wx.FONTSTYLE_NORMAL,
                                weight=wx.FONTWEIGHT_NORMAL,
                                encoding=wx.FONTENCODING_UTF8
                                ),
        },
    }


class ConfirmDialog(wx.Dialog):

    def __init__(self, parent, text="", 
                 margin=10, borderRadio=10):
        wx.Dialog.__init__(self, parent, style=wx.STAY_ON_TOP)
        # Get data to show
        self.parent = parent
        self._margin = margin
        self._borderRadio = borderRadio
        self._text = text
        self._font = None

        self.initializeTools()

        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_SHOW, self._sendRefresh)
        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)

        self._setWidgets()
        self._layout()
        wx.CallAfter(self.Refresh)

    def _sendRefresh(self, e):
        if self.IsShown():
            print("send refresh")
            self.Refresh()

    def _setWidgets(self):
        self.panel = wx.Panel(self)
        self.message = wx.StaticText(self.panel, label=self.GetText())
        self.message.SetForegroundColour(self.tools['ForegroundColor'])
        self.message.SetBackgroundColour(self.tools['BackgroundColor'])

        self.cancelBtn  = wx.Button(self.panel, id=wx.ID_CANCEL, label="Cancel")
        self.okBtn      = wx.Button(self.panel, id=wx.ID_OK, label="Ok")

    def _layout(self):
        self.vSizer = wx.BoxSizer(wx.VERTICAL)
        self.buttonsSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.buttonsSizer.Add(self.okBtn)
        self.buttonsSizer.AddSpacer(20)
        self.buttonsSizer.Add(self.cancelBtn)
        self.vSizer.Add(self.message,      0, wx.CENTER|wx.BOTTOM, 5)
        self.vSizer.Add(self.buttonsSizer, 0, wx.CENTER|wx.TOP, 5)

        self.panel.SetSizer(self.vSizer)
        self.vSizer.Fit(self.panel)

    def SetMargin(self, margin):
        self._margin = margin
        self.Refresh()

    def GetMargin(self):
        return self._margin

    def SetBorderRadio(self, borderRadio):
        self._borderRadio = borderRadio
        self.Refresh()

    def GetBorderRadio(self):
        return self._borderRadio

    def SetText(self, text):
        self._text = text
        self.Refresh()

    def GetText(self):
        return self._text

    def GetFont(self):
        if not self._font:
            self._font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
        return self._font

    def initializeTools(self):

        self.borderWidth = 6

        backColour = self.GetBackgroundColour()
        self.tools = GetThemeTools(self.borderWidth, backColour)

        self._font = self.tools['Fonts']['Brief']

    def OnPaint(self, event):
        print("Paint Event")
        dc = wx.BufferedPaintDC(self)
        self.Draw(dc)
        event.Skip()

    def Draw(self, dc):

        print("Draw Function")
        margin = self.GetMargin()
        borderRadio = self.GetBorderRadio()
        text = self.GetText()

        self.Layout()

        dc.SetBackground(self.tools['Brushes']['Background'])
        dc.SetFont(self.GetFont())
        dc.SetTextBackground(self.tools['BackgroundColor'])
        dc.Clear()

        (H, W) = self.GetSize()

        # Draw Border
        dc.SetPen(self.tools['Pens']['DarkRectSolidBorder'])
        dc.SetBrush(self.tools['Brushes']['RectBoxFilling'])
        dc.DrawRoundedRectangle( 0, 0, H, W, borderRadio)

    def OnEraseBackground(self, event):
        pass


class AppFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "Custom Dialog Test")
        panel = wx.Panel(self)

        frameSizer = wx.BoxSizer(wx.VERTICAL)
        panelSizer = wx.BoxSizer(wx.VERTICAL)
        btn = wx.Button(panel, label="Show Dialog")
        btn.Bind(wx.EVT_BUTTON, self.ShowDlg)

        panelSizer.Add(btn, 0, wx.ALL, 20)

        panel.SetSizer(panelSizer)
        self.SetSizer(frameSizer)

        panelSizer.Fit(panel)
        self.Layout()

        self.Show()

    def ShowDlg(self, event):
        dia = ConfirmDialog(self, "Custom Dialog\nTest\nThird Line")
        if dia.ShowModal() == wx.ID_OK:
            print("Clicked OK")
        else:
            print("Clicked CANCEL")



app = wx.App(False)
frame = AppFrame()
app.MainLoop()

2 个答案:

答案 0 :(得分:1)

您已将绘图事件处理程序绑定到对话框,但该对话框有一个完全覆盖对话框的面板。由于对话框的表面永远不会暴露(因为它位于面板下),因此它永远不需要绘制,因此它永远不会从系统中收到绘制事件。

在大多数情况下,您不需要将面板作为对话框中的顶部元素,因此您可能希望将其删除并仅使用self.panel替换该部分代码中的所有self

答案 1 :(得分:0)

按照Drawing To Panel Inside of Frame上的提示:

  • 我错了Paint事件的绑定

    self.panel.Bind(wx.EVT_PAINT, self.OnPaint)
    self.panel.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
    

    由于某些原因,我仍然没有完全得到(self.Bind vs self.button.Bind的例子)为什么专家组不会Skip()油漆事件;导致self从未意识到油漆事件。

  • 画布的父母身份:

    dc = wx.BufferedPaintDC(self.panel)
    

    在从wx.PopupWindow播放一些子类后(导致窗口尺寸不合适,我无法正确地居中于框架中)后,我意识到DC正在面板下方呈现。由于self.panelself的孩子,因此只有self被绘制。


不是错误,但在Paint事件中,面板或对话框似乎恢复到默认大小。如果面板适合,则会调整对话框的大小,并在Paint事件中再次居中窗口,然后将引发新的Paint Events并显示闪烁。由于这是一个参数化的静态对话框,因此可以在self._layout()的末尾修复尺寸:

self.panel.Fit()
minSize = self.panel.GetSize()
self.SetMinSize(minSize)
self.SetMaxSize(minSize)