wxPython:尝试制作停靠窗口,绑定父级EVT_ACTIVATE导致无法调整大小
我正在尝试制作一个简单的停靠框架,它可以停靠在一个父窗口上,并跟随父窗口移动。目前我有以下代码:
class DockingFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, style=wx.CAPTION)
parent.Bind(wx.EVT_MOVE, self.OnParentMove)
parent.Bind(wx.EVT_ACTIVATE, self.OnParentActivate)
parent.Bind(wx.EVT_SHOW, self.OnParentShow)
def OnParentMove(self, moveEvent):
print "Docked frame parent moved"
pr = positioning.position(
self.Rect,
my='right_top', at='left_top', of=self.Parent.Rect)
self.Move(pr.top_left)
moveEvent.Skip()
def OnParentActivate(self, event):
print "Docked frame parent activated"
self.Raise()
event.Skip()
def OnParentShow(self, event):
print "Docked frame parent showed"
self.Show(event.GetShow())
event.Skip()
class MainFrame(wx.Frame):
def __init__(self, title):
wx.Frame.__init__(self, None, title=title)
self.info_frame = DockingFrame(self)
self.Show(True)
这个代码的效果是,当我移动父窗口时,停靠的窗口也会跟着移动;而且当我点击父窗口时,停靠窗口会自动抬起来。不过,这样做严重影响了父窗口的功能。我无法再关闭或调整父窗口的大小,每次点击父窗口时,都会出现很多“停靠框架父窗口被激活”的消息。看起来我对wxPython的一些基本概念理解得不太对。到底发生了什么,我该怎么解决呢?
我注意到aui
似乎支持停靠功能,但相关文档很少,所以我还没有尝试过。如果有人能提供一个简单的代码示例,教我如何用aui
让一个Frame
停靠到另一个Frame
上,我也可以尝试这种方法。
另外,我在这个应用中还使用了pygame
和twisted
,这可能会有影响,也可能没有……
2 个回答
0
这个技巧在于,EVT_ACTIVATE
事件在激活和取消激活时都会触发。下面的代码就能正常工作。如果父窗口被激活,那么这个停靠窗口就会自己抬起来,并且紧接着会把父窗口也抬起来。
class DockingFrame(wx.Frame):
def __init__(self, parent):
self.handleParentActiveState = 'noTriggers'
wx.Frame.__init__(self, parent, title="Last Hand", style=wx.CAPTION)
parent.Bind(wx.EVT_MOVE, self.OnParentMove)
parent.Bind(wx.EVT_ACTIVATE, self.OnParentActivate)
self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
parent.Bind(wx.EVT_SHOW, self.OnParentShow)
def OnActivate(self, event):
event.Skip()
if not event.GetActive():
return
if self.handleParentActiveState == 'activateParentNext':
self.handleParentActiveState = 'resetTriggers'
self.Parent.Raise()
def OnParentActivate(self, event):
event.Skip()
if not event.GetActive():
return
if self.handleParentActiveState == 'noTriggers':
self.handleParentActiveState = 'activateParentNext'
self.Raise()
elif self.handleParentActiveState == 'resetTriggers':
self.handleParentActiveState = 'noTriggers'
def OnParentMove(self, moveEvent):
pr = positioning.position(
self.Rect,
my='right_top', at='left_top', of=self.Parent.Rect)
self.Move(pr.top_left)
moveEvent.Skip()
def OnParentShow(self, event):
event.Skip()
self.Show(event.GetShow())
2
当然,最简单的方法就是直接使用 wx.FRAME_FLOAT_ON_PARENT
这个样式...
class DockingFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, title="Last Hand",
style=wx.CAPTION | wx.FRAME_FLOAT_ON_PARENT)
parent.Bind(wx.EVT_MOVE, self.OnParentMove)
parent.Bind(wx.EVT_SHOW, self.OnParentShow)
def SnapToParent(self):
print "*Snapping to parent"
pr = positioning.position(
self.Rect,
my='right_top', at='left_top', of=self.Parent.Rect)
self.Move(pr.top_left)
def OnParentMove(self, moveEvent):
moveEvent.Skip()
self.SnapToParent()
def OnParentShow(self, event):
event.Skip()
print "Parent %s" % ("Hide", "Show")[event.GetShow()]
self.Show(event.GetShow())