2016-04-10 2 views
0

У меня есть простое приложение, которое отображает список пользовательских сведений в wx.VListBox Каждый элемент отображается с помощью OnDrawItem(), и все работает отлично, когда мне нужно нарисовать текст, линию или изображение.Нарисуйте пользовательскую панель с контролем в wx.VListBox OnDrawItem()

Приложение вид:

enter image description here

Как добавить около нескольких текстовых меток (имя и адрес электронной почты) также несколько wx.ComboBox, несколько wx.ComboBox в каждой строке?

Я рассматриваю решение как визуализацию некоторого пользовательского элемента управления на основе wx.Panel, который имеет все элементы управления, установленные на этой панели, но как визуализировать панель с ее дочерними элементами управления в каждой строке wx.VListBox?

Мой текущий полный код (просто скопировать/вставить):

import wx 


class UserInfo(object): 
    def __init__(self, name, email, *args, **kwargs): 
     super(self.__class__, self).__init__(*args, **kwargs) 

     self.name = name 
     self.email = email 


class UserListBox(wx.VListBox): 
    def __init__(self, parent, users, *args, **kwargs): 
     super(self.__class__, self).__init__(parent, *args, **kwargs) 

     self.bh = 10 
     self.users = users 

     self.SetItemCount(len(self.users)) 

    def OnMeasureItem(self, idx): 
     image_height = self.bh + 4 
     name_size = self.GetTextExtent(self.users[idx].name) 
     email_size = self.GetTextExtent(self.users[idx].email) 
     return max(image_height, name_size[1] + email_size[1] + 6) 

    def OnDrawSeparator(self, dc, rect, idx): 
     oldpen = dc.GetPen() 
     dc.SetPen(wx.Pen(wx.BLACK)) 
     dc.DrawLine(rect.x, rect.y, rect.x + rect.width, rect.y) 
     rect.Deflate(0, 2) 
     dc.SetPen(oldpen) 

    def OnDrawItem(self, dc, rect, n): 
     # Draw the name label to the right of the bitmap 
     textx = rect.x + 2 + self.bh + 2 
     lblrect = wx.Rect(textx, rect.y, 
          rect.width - textx, 
          rect.height) 
     user = self.users[n] 
     dc.DrawLabel(user.name, lblrect, 
        wx.ALIGN_LEFT | wx.ALIGN_TOP) 
     dc.DrawLabel(user.email, lblrect, 
        wx.ALIGN_LEFT | wx.ALIGN_BOTTOM) 


class AppFrame(wx.Frame): 
    def __init__(self, parent, *args, **kwargs): 
     super(self.__class__, self).__init__(parent, *args, **kwargs) 

     sizer = wx.BoxSizer(wx.VERTICAL) 
     self.SetSizer(sizer) 

     users = list() 
     for n in range(100): 
      users.append(UserInfo('John %s' % n, '[email protected]')) 

     listobx = UserListBox(self, users, size=(150, 250), style=wx.BORDER_SUNKEN) 
     sizer.Add(listobx, flag=wx.EXPAND) 

     btn = wx.Button(self, label='Do it!') 
     sizer.Add(btn) 


class DemoApp(wx.App): 
    def OnInit(self): 
     self.frame = AppFrame(None, title="App Demo") 
     self.frame.Show() 
     return True 

if __name__ == '__main__': 
    app = DemoApp() 
    app.MainLoop() 

ответ

1

Вы можете использовать методы класса wxRendererNative рисовать изначально прогнозное представление пользовательских элементов управления, например в вашем случае вы будете использовать DrawComboBoxDropButton(). Вам нужно будет создать реальный wxComboBox всякий раз, когда нажимается изображение (или, может быть, даже когда мышь просто нависает над ним), чтобы пользователь мог изменить его значение.

+0

Спасибо, имеет смысл. Но как отслеживать клики/зависание этого конкретного изображения по всей ячейке списка? И еще более интересно - как на месте это изображение с реальным управлением в тех же координатах и ​​снова удалять управление. Можете ли вы предложить любое место с образцом кода? – Zelid

+0

Вы можете привязываться к событию перемещения мыши и использовать 'VirtualHitTest()', чтобы получить элемент под ним, но поиск точного местоположения комбо-кнопки может оказаться сложным, если вы можете просто полностью перекрывать ячейку с помощью реального combobox, это было бы самым простым решением. Удаление элемента управления просто: просто сделайте это, когда он потеряет фокус. –