Dialog 的 ShowModal() 不会发送 EVT_PAINT
Dialog's ShowModal() won't send EVT_PAINT
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()
遵循 Drawing To Panel Inside of Frame 上的提示:
Paint Event绑定错误
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
永远不会意识到 Paint 事件。
以及 canvas 的父母身份:
dc = wx.BufferedPaintDC(self.panel)
玩了一点 wx.PopupWindow
的子类后(这导致 Window 尺寸不佳,我无法在框架中正确居中)我意识到 DC 被渲染在控制板。这是有道理的,因为 self.panel
是 self
的 child,所以只绘制了 self
。
不是错误,但在 Paint 事件中,面板或对话框似乎恢复到默认大小。如果面板适合,调整对话框大小,并且 window 在 Paint Event 中再次居中,然后将引发新的 Paint Events 并出现闪烁。由于这是一个参数化的静态对话框,尺寸可以固定在 self._layout()
:
的末尾
self.panel.Fit()
minSize = self.panel.GetSize()
self.SetMinSize(minSize)
self.SetMaxSize(minSize)
您已将绘制事件处理程序绑定到对话框,但对话框有一个面板完全覆盖了对话框。由于对话框的表面永远不会暴露(因为它在面板下面),所以它永远不需要绘制,所以它永远不会从系统接收到绘制事件。
在大多数情况下,您不需要将面板作为对话框的顶部元素,因此您可能希望将其删除并仅将那部分代码中的所有 self.panel
替换为 self
.
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()
遵循 Drawing To Panel Inside of Frame 上的提示:
Paint Event绑定错误
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
永远不会意识到 Paint 事件。以及 canvas 的父母身份:
dc = wx.BufferedPaintDC(self.panel)
玩了一点
wx.PopupWindow
的子类后(这导致 Window 尺寸不佳,我无法在框架中正确居中)我意识到 DC 被渲染在控制板。这是有道理的,因为self.panel
是self
的 child,所以只绘制了self
。
不是错误,但在 Paint 事件中,面板或对话框似乎恢复到默认大小。如果面板适合,调整对话框大小,并且 window 在 Paint Event 中再次居中,然后将引发新的 Paint Events 并出现闪烁。由于这是一个参数化的静态对话框,尺寸可以固定在 self._layout()
:
self.panel.Fit()
minSize = self.panel.GetSize()
self.SetMinSize(minSize)
self.SetMaxSize(minSize)
您已将绘制事件处理程序绑定到对话框,但对话框有一个面板完全覆盖了对话框。由于对话框的表面永远不会暴露(因为它在面板下面),所以它永远不需要绘制,所以它永远不会从系统接收到绘制事件。
在大多数情况下,您不需要将面板作为对话框的顶部元素,因此您可能希望将其删除并仅将那部分代码中的所有 self.panel
替换为 self
.