2009-02-26 32 views
4

Belirli satırların standart renginin yerine kırmızı renkte olmasını istiyorum (pencerelerdeki mavi), durumu gösterebileceğim şekilde. WxPython'da bunun mümkün olup olmadığını bilen var mı? Eğer wx.ListCtrl kaynaklanıyor senin sınıfındawxPython wxListCtrl seçili satır rengi

cevap

4

İstediğiniz şeyi yapmak için, belirli öğeler seçildiğinde farklı bir seçim rengine sahip olmak için, win32'ye girmeniz gerekecektir. Neyse ki, python'da bunu yapmak çok zor değil. Ancak kod platformunuzu bağımlı hale getirir. Bugün küçük bir programda denedim. Eğer Tür "Kaya" değilse, seçimi turuncu yaparım. İşte bazı ekran görüntüleri.

Kaya Öğeler Seçilmiş alt text http://img26.imageshack.us/img26/981/soshot1.jpg

Karışık Öğeler Seçilmiş. Dikkat edin, RnB ve Blues, Orange alt text http://img258.imageshack.us/img258/1307/soshot2.jpg Burada, kod bulunmaktadır. İlk başta korkutucu görünüyor ama eğer herhangi bir win32 biliyorsanız, o kadar da kötü değil. pywin32 paketini ve std ctypes kitaplıklarını kullanıyorum. Win32con modülünde bulunmayan bazı SDK sabitlerini tanımlamak zorunda kaldım.

import sys 
import wx 
import wx.lib.mixins.listctrl as listmix 

import win32api 
import win32gui 
import win32con 
import win32gui_struct 
import commctrl 
import ctypes 
from ctypes.wintypes import BOOL, HWND, RECT, UINT, DWORD, HDC, DWORD, LPARAM, COLORREF 

LVM_FIRST = 0x1000 
LVM_GETSUBITEMRECT=(LVM_FIRST + 56) 
LVIR_BOUNDS    =0 
LVIR_ICON    =1 
LVIR_LABEL    =2 
LVIR_SELECTBOUNDS  =3 
DEFAULT_GUI_FONT =17 

#LPNMHDR 
class NMHDR(ctypes.Structure): 
    pass 
INT = ctypes.c_int 
NMHDR._fields_ = [('hwndFrom', HWND), ('idFrom', UINT), ('code', INT)] 
LPNMHDR = ctypes.POINTER(NMHDR) 

#LPNMCUSTOMDRAW 
class NMCUSTOMDRAW(ctypes.Structure): 
    pass 
NMCUSTOMDRAW._fields_ = [('hdr', NMHDR), ('dwDrawStage', DWORD), ('hdc', ctypes.c_int), 
         ('rc', RECT), ('dwItemSpec', DWORD), ('uItemState', UINT), 
         ('lItemlParam', LPARAM)] 
LPNMCUSTOMDRAW = ctypes.POINTER(NMCUSTOMDRAW) 

#LPNMLVCUSTOMDRAW 
class NMLVCUSTOMDRAW(ctypes.Structure): 
    pass 
NMLVCUSTOMDRAW._fields_ = [('nmcd', NMCUSTOMDRAW), 
          ('clrText', COLORREF), 
          ('clrTextBk', COLORREF), 
          ('iSubItem', ctypes.c_int), 
          ('dwItemType', DWORD), 
          ('clrFace', COLORREF), 
          ('iIconEffect', ctypes.c_int), 
          ('iIconPhase', ctypes.c_int), 
          ('iPartId', ctypes.c_int), 
          ('iStateId', ctypes.c_int),       
          ('rcText', RECT), 
          ('uAlign', UINT) 
          ] 
LPNMLVCUSTOMDRAW = ctypes.POINTER(NMLVCUSTOMDRAW) 


musicdata = { 
1 : ("Bad English", "The Price Of Love", "Rock"), 
2 : ("DNA featuring Suzanne Vega", "Tom's Diner", "Rock"), 
3 : ("George Michael", "Praying For Time", "Rock"), 
4 : ("Gloria Estefan", "Here We Are", "Rock"), 
5 : ("Linda Ronstadt", "Don't Know Much", "Rock"), 
6 : ("Michael Bolton", "How Am I Supposed To Live Without You", "Blues"), 
7 : ("Paul Young", "Oh Girl", "Rock"), 
8 : ("Paula Abdul", "Opposites Attract", "Rock"), 
9 : ("Richard Marx", "Should've Known Better", "Rock"), 
10 : ("Bobby Brown", "My Prerogative", "RnB"), 
} 




class MyListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin): 
    def __init__(self, parent, ID, pos=wx.DefaultPosition, 
       size=wx.DefaultSize, style=0): 
     wx.ListCtrl.__init__(self, parent, ID, pos, size, style) 
     listmix.ListCtrlAutoWidthMixin.__init__(self) 

    def ShouldCustomDraw(self, row): 
     if self.IsSelected(row): 
      listitem = self.GetItem(row, 2) 
      genre = listitem.GetText() 

      return genre != "Rock" 


    def CustomDraw(self, lpcd):   
     if lpcd.contents.nmcd.dwDrawStage == commctrl.CDDS_PREPAINT: 
      return (True, commctrl.CDRF_NOTIFYITEMDRAW) 

     if lpcd.contents.nmcd.dwDrawStage == commctrl.CDDS_ITEMPREPAINT:     
      if self.ShouldCustomDraw(lpcd.contents.nmcd.dwItemSpec): 
       #do custom drawing for non Rock selected rows 
       #paint the selection background 
       color = win32api.RGB(255, 127, 0) #orange 
       brush = win32gui.CreateSolidBrush(color) 
       r = lpcd.contents.nmcd.rc 
       win32gui.FillRect(int(lpcd.contents.nmcd.hdc), (r.left+4, r.top, r.right, r.bottom), brush)     
       win32gui.DeleteObject(brush) 
       return (True, commctrl.CDRF_NOTIFYSUBITEMDRAW)      

     if lpcd.contents.nmcd.dwDrawStage == commctrl.CDDS_ITEMPREPAINT|commctrl.CDDS_SUBITEM:     
      row = lpcd.contents.nmcd.dwItemSpec 
      col = lpcd.contents.iSubItem 
      item = self.GetItem(row, col) 
      text = item.GetText() 
      #paint the text 
      rc = RECT() 
      rc.top = col 
      if col > 0: 
       rc.left = LVIR_BOUNDS 
      else: 
       rc.left = LVIR_LABEL 
      success = win32api.SendMessage(self.Handle, LVM_GETSUBITEMRECT, row, ctypes.addressof(rc)) 
      if col > 0: 
       rc.left += 5 
      else: 
       rc.left += 2 
      rc.top += 2 

      if success:     
       oldColor = win32gui.SetTextColor(lpcd.contents.nmcd.hdc, win32gui.GetSysColor(win32con.COLOR_HIGHLIGHTTEXT))     
       win32gui.DrawText(lpcd.contents.nmcd.hdc, text, len(text), (rc.left, rc.top, rc.right, rc.bottom), win32con.DT_LEFT|win32con.DT_VCENTER) 
       win32gui.SetTextColor(lpcd.contents.nmcd.hdc, oldColor)         

      return (True, commctrl.CDRF_SKIPDEFAULT) 


     # don't need custom drawing 
     return (True, commctrl.CDRF_DODEFAULT) 


class MyFrame(wx.Frame): 
    def __init__(self, *args, **kwds): 
     wx.Frame.__init__(self, *args, **kwds) 
     self._sizer = wx.BoxSizer(wx.VERTICAL) 
     tID = wx.NewId() 
     self._ctl = MyListCtrl(self, tID, 
           style=wx.LC_REPORT 
           #| wx.BORDER_SUNKEN 
           | wx.BORDER_NONE 
           | wx.LC_EDIT_LABELS 
           | wx.LC_SORT_ASCENDING 
           #| wx.LC_NO_HEADER 
           #| wx.LC_VRULES 
           #| wx.LC_HRULES 
           #| wx.LC_SINGLE_SEL 
           ) 
     self._sizer.Add(self._ctl, 1, wx.EXPAND, 3) 
     self.PopulateList() 

     self.oldWndProc = win32gui.SetWindowLong(self.GetHandle(), win32con.GWL_WNDPROC, self.MyWndProc) 


    def MyWndProc(self, hWnd, msg, wParam, lParam): 

     if msg == win32con.WM_NOTIFY: 
      hwndFrom, idFrom, code = win32gui_struct.UnpackWMNOTIFY(lParam) 
      if code == commctrl.NM_CUSTOMDRAW and hwndFrom == self._ctl.Handle:     
       lpcd = ctypes.cast(lParam, LPNMLVCUSTOMDRAW) 
       retProc, retCode = self._ctl.CustomDraw(lpcd) 

       if retProc: 
        return retCode 


     # Restore the old WndProc. Notice the use of wxin32api 
     # instead of win32gui here. This is to avoid an error due to 
     # not passing a callable object. 
     if msg == win32con.WM_DESTROY: 
      win32api.SetWindowLong(self.GetHandle(), 
           win32con.GWL_WNDPROC, 
           self.oldWndProc) 

     # Pass all messages (in this case, yours may be different) on 
     # to the original WndProc 
     return win32gui.CallWindowProc(self.oldWndProc, 
            hWnd, msg, wParam, lParam) 

    def PopulateList(self): 
     self._ctl.InsertColumn(0, "Artist") 
     self._ctl.InsertColumn(1, "Title") 
     self._ctl.InsertColumn(2, "Genre") 

     items = musicdata.items() 

     for key, data in items:    
      index = self._ctl.InsertStringItem(sys.maxint, data[0]) 
      self._ctl.SetStringItem(index, 1, data[1]) 
      self._ctl.SetStringItem(index, 2, data[2]) 
      self._ctl.SetItemData(index, key) 


     self._ctl.SetColumnWidth(0, wx.LIST_AUTOSIZE) 
     self._ctl.SetColumnWidth(1, wx.LIST_AUTOSIZE) 
     self._ctl.SetColumnWidth(2, 100) 

     self.currentItem = 0 

class MyApp(wx.App): 
    def OnInit(self): 
     frame = MyFrame(None, -1, 'wxListCtrl StackOverflow') 
     frame.Show() 
     self.SetTopWindow(frame) 
     return 1 

if __name__ == "__main__": 
    app = MyApp(0) 
    app.MainLoop() 
7

kullanarak öğe nitelikleri vaktinden başlatılır

def OnGetItemAttr(self, item): 
    return self.normalAttr[item % 2] 
# 

ağır basan

bakmak:

self.normalAttr = [] 
    self.normalAttr.append(wx.ListItemAttr()) 
    grayAttr = wx.ListItemAttr() 
    grayAttr.SetBackgroundColour(lightGray) 
    self.normalAttr.append(grayAttr) 

Yani bu durumda, Varsayılan ve açık gri özniteliği arasında arka plan renkleri değiştiriyorum.

Bu işlev her satır için boyalı olarak çağrılır, böylece her türlü durumu belirtmek için kullanabilirsiniz. Satır seçilirse kolay bir durum olmalıdır.

İlgili konular