2015年1月19日

Python - 使用 FoldPanelBar 實作可摺疊 ListView


之前為了一些需求,需要使用到類似 line 通訊錄的那種可摺疊的畫面。在 android 可用 BaseExpandableListAdapter 實作;ios 則可用 TableView 的 group 來實作,那 python 呢?
上網爬文研究了幾天,看到有人說 python 官方 demo 裡面有可以做到摺疊的畫面,於是自己加工了一下,做出類似 BaseExpandableListAdapter 的東西...
成品如下圖:
以下就簡單說明一下是如何實作,最後面有範例提供給大家取用

架構



實作步驟

  1. 建立一個 ScrollView
  2. 建立一個 FoldPanelBar
  3. 加入 FoldPanel ( group view )
  4. 加入 child view ( 可自訂任何畫面,主要還是以 panel 為最底層 )

#建立一個 FoldPanelBar
self.panel = fpb.FoldPanelBar(self.parentView, 2, wx.DefaultPosition, self.parentView.GetSize(),
                           agwStyle=fpb.FPB_VERTICAL)
#設定 group 展開/收合的圖片
Images = wx.ImageList(27,27)  #寬高一定要跟圖片一樣,不然不能載入
Images.Add(wx.Bitmap( u"image/news_open.png", wx.BITMAP_TYPE_ANY ))
Images.Add(wx.Bitmap( u"image/news_close.png", wx.BITMAP_TYPE_ANY ))

#設定 group 的顏色等 style
cs = foldPanel.CaptionBarStyle()
cs.SetCaptionStyle(foldPanel.CAPTIONBAR_FILLED_RECTANGLE)
cs.SetFirstColour(wx.Colour(85,147,177,0))
cs.SetCaptionColour(wx.WHITE)

titleDir = {
          0: "myProfile",
          1: "Favorites",
          2: "group",
          3: "application",
          4: "supplier",
          5: "company"
}

#list 是空時
if len(self.coll)==0:
    for i in range(0, MAX_TITLE_COUNT+1, +1):
 #增加一個 group
        item = self.panel.AddFoldPanel(titleDir[i], collapsed=False, foldIcons=Images, cbstyle=cs)
 #增加一條分隔線
        self.panel.AddFoldPanelSeparator(item, spacing=0)
 #綁定 action
        item.Bind(fpb.EVT_CAPTIONBAR, functools.partial(self.OnPressCaption, groupPosition=i))
        self.pitemList.append(item)
else:
    for i in range(0, len(self.coll), +1):
 #增加一個 group
        item = self.panel.AddFoldPanel(titleDir[self.coll[i][0]], collapsed=False, foldIcons=Images, cbstyle=cs)
        childItemList = []

        for j in range(0, len(self.coll[i][1]), +1):
            isGroupTitle = False
            bitmapPaht = u"image/name_icon1.png"
            name = "test"
            positionType = self.coll[i][0]
            vo = self.coll[i][1][j]
            if positionType == LOGIN_USER:
                print "LOGIN_USER"
                name = vo
            elif positionType == FAV_USER:
                print "FAV_USER"
                name = vo
            elif positionType == CHAT_GROUP:
                print "CHAT_GROUP"
                bitmapPaht = u"image/name_icon2.png"
                name = vo
            elif positionType == APP_USER:
                bitmapPaht = u"image/name_icon3.png"
                print "APP_USER"
                name = vo
            elif positionType == SUPPLIER:
                print "SUPPLIER"
                name = vo
            elif positionType == COMPANY:
                print "COMPANY"
                name = vo

            temp = wx.Bitmap( bitmapPaht, wx.BITMAP_TYPE_ANY )
            if isGroupTitle:
                isGroupTitle = False
  #==================================
  #增加一個 child view
                panel = wx.Panel(item, j)
                childItemList.append(panel)
                panel.BackgroundColour = wx.WHITE
                bSizer_gorupTitlePanel = wx.BoxSizer( wx.HORIZONTAL )

                #最上層group
                print "name:"+name
                print "fullname:"+vo.fullname
                print "groupname:"+vo.groupname
                st_groupPath = wx.StaticText( panel, wx.ID_ANY, name, (3, 12), wx.DefaultSize, 0 )
                st_groupPath.Wrap( -1 )

                panel.SetClientSize(wx.Size( -1, temp.GetHeight()))
  #==================================

            else:
  #==================================
  #增加一個 child view
                panel = wx.Panel(item, j)
                childItemList.append(panel)
                panel.BackgroundColour = wx.WHITE

                bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
                size = temp.GetWidth(), temp.GetHeight()

                imgbtn_icon = wx.BitmapButton( panel, j, temp, (5, 5), size, 0 )
                bSizer2.Add( imgbtn_icon, 0, wx.ALL|wx.EXPAND, 5 )

                st_name = wx.StaticText( panel, j, name, (temp.GetWidth()+10, temp.GetHeight()/2), wx.DefaultSize, 0 )
                st_name.Wrap( -1 )
                bSizer2.Add( st_name, 1, wx.ALL|wx.EXPAND, 0 )

                panel.SetClientSize(wx.Size( -1, temp.GetHeight()+10))
  #==================================
  #綁定 action
                panel.Bind(wx.EVT_LEFT_DCLICK, functools.partial(self.doubleClick, groupPosition=i, vo=vo), id=j)
                panel.Bind(wx.EVT_LEFT_DOWN, functools.partial(self.OnItemDown, groupPosition=i, obj="test msg"), id=j)
                panel.Bind(wx.EVT_ENTER_WINDOW, functools.partial(self.onMouseOver, groupPosition=i), id=j)
                panel.Bind(wx.EVT_LEAVE_WINDOW, functools.partial(self.onMouseLeave, groupPosition=i), id=j)
                st_name.Bind(wx.EVT_LEFT_DCLICK, functools.partial(self.doubleClick, groupPosition=i, vo=vo), id=j)
                imgbtn_icon.Bind(wx.EVT_BUTTON, functools.partial(self.clickIcon, groupPosition=i, obj="test msg"), id=j)
  #==================================

     #將 child view add 到 FoldPanel 中
            self.panel.AddFoldPanelWindow(item, panel, fpb.FPB_ALIGN_WIDTH, 0)
            #==================================
            #增加一條分隔線
            self.panel.AddFoldPanelSeparator(item, spacing=0)
            #==================================
 #綁定 action
        item.Bind(fpb.EVT_CAPTIONBAR, functools.partial(self.OnPressCaption, groupPosition=i))

        self.itemList.append(childItemList)
        self.pitemList.append(item)

References