如何解决wxPython中的自定义可折叠列表,鼠标事件未传播到父级
我正在使用wxPython编写GUI待办事项列表应用程序,并且需要包含可折叠项的列表。我了解wx.CollapsiblePane
和wx.lib.agw.foldpanelbar.FoldPanelBar
,但都不会让您以复杂的方式自定义折叠项标签。我想要一个简单的待办事项标题以及一个可单击的复选框作为折叠视图,单击复选框的标签后,它会展开以显示注释,截止日期等。我已经使用静态文本创建了原型,但是即使那个也不起作用。使用复选框只会通过添加更多的鼠标事件侦听器使其变得更加复杂。
如果您仅在StaticText
中使用ItemPanel
窗口(已推出),则可以使用。 为什么它不适用于自定义面板类?
import wx
PADDING = 10
class App(wx.App):
def OnInit(self):
self.data = [
{'title':'1st','content':'First'},{'title':'2nd','content':'Second'},{'title':'3rd','content':'Third'},]
frame = ListFrame()
frame.Show()
self.SetTopWindow(frame)
return True
class ListFrame(wx.Frame):
def __init__(self,title="List",size=(250,500)):
wx.Frame.__init__(self,None,-1,title=title,size=size)
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(wx.StaticText(panel,label='List Title'),flag=wx.EXPAND|wx.ALL,border=PADDING)
sizer.Add(wx.StaticLine(panel,style=wx.LI_HORIZONTAL),flag=wx.EXPAND)
sizer.Add(ListPanel(panel),proportion=1,flag=wx.EXPAND)
panel.SetSizer(sizer)
class ListPanel(wx.ScrolledWindow):
def __init__(self,parent):
super().__init__(parent)
self.data = wx.GetApp().data
self.SetScrollRate(0,5)
self.sizer = wx.BoxSizer(wx.VERTICAL)
for item in self.data:
item_panel = ItemPanel(self,item)
self.sizer.Add(item_panel,flag=wx.ALIGN_LEFT|wx.LEFT|wx.RIGHT|wx.BottOM,border=PADDING)
self.SetSizer(self.sizer)
class ItemPanel(wx.Control):
def __init__(self,parent,item):
self.parent = parent
super().__init__(self.parent)
self.collapsed = True
self.item = item
self.sizer = wx.BoxSizer(wx.VERTICAL)
#self.panel_collapsed = wx.StaticText(self,label='> '+item['title'])
#self.panel_expanded = wx.StaticText(self,label='v '+item['title']+'\n\t'+item['content'])
self.panel_collapsed = ItemPanelCollapsed(self)
self.panel_expanded = ItemPanelExpanded(self)
self.panel_collapsed.Bind(wx.EVT_LEFT_UP,self.OnToggleView)
self.panel_expanded.Bind(wx.EVT_LEFT_UP,self.OnToggleView)
#self.Bind(wx.EVT_LEFT_UP,self.OnToggleView)
self.sizer.Add(self.panel_collapsed,flag=wx.EXPAND)
self.sizer.Add(self.panel_expanded,flag=wx.EXPAND)
self.sizer.Hide(self.panel_expanded)
self.SetSizer(self.sizer)
def OnToggleView(self,event):
if self.collapsed:
self.sizer.Hide(self.panel_collapsed)
self.sizer.Show(self.panel_expanded)
else:
self.sizer.Hide(self.panel_expanded)
self.sizer.Show(self.panel_collapsed)
self.collapsed = not self.collapsed
self.sizer.Layout()
self.parent.sizer.Layout()
class ItemPanelCollapsed(wx.Control):
def __init__(self,parent):
super().__init__(parent,style=wx.BORDER_NONE)
sizer = wx.BoxSizer(wx.VERTICAL)
#sizer.Add(wx.CheckBox(self,label=parent.item['title']),flag=wx.EXPAND)
sizer.Add(wx.StaticText(self,label='> '+parent.item['title']),flag=wx.EXPAND)
self.SetSizer(sizer)
class ItemPanelExpanded(wx.Control):
def __init__(self,label='v '+parent.item['title']),label=parent.item['content']),flag=wx.EXPAND)
self.SetSizer(sizer)
if __name__ == '__main__':
app = App(False)
app.MainLoop()
我还尝试将鼠标事件绑定到子窗口的ItemPanel
(已注释掉) 上,但是后来又无法正常工作了。所以我想这与how the mouse events are propagated up the chain有关。因此,我还尝试让所有自定义类都继承自wx.Panel
或wx.Window
,但这并没有改变行为。
可选:由于我是wxPython的新手,如果您可以回答这些相关的样式问题,那就好了
- 这是完成任务的正确方法吗?我是否应该直接修改ItemPanel而不是隐藏/取消隐藏嵌套元素?
- 如果此方法在某种程度上是正确的,那么从
ItemPane.OnToggleView
改变“布局”布局的最佳方法是什么?将所有parent.sizer.Layout()
都调用到链上(想象更多的嵌套)似乎有些麻烦…… - 这是进行模型/视图分离的正确方法吗?将数据保存在
App.data
中,并使用wx.GetApp()
从窗口访问数据。App.data
更改后,如何自动更新视图? - 定义全局样式的正确方法是什么?我使用了模块范围的常量
PADDING
,但也许将其放入App
并通过wx.GetApp()
访问它会更好吗?但是基本上每个窗口都会调用此函数吗? - 在这种情况下要继承的正确类是什么?我将
wx.Panel
用于“高级”元素,将wx.Control
用于更多的基本小部件。我不太了解wx.Window
,wx.Panel
和wx.control
之间的区别(这就是为什么我从ListPanel
继承它时将其称为wx.ScrolledWindow
的原因)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。