微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 GridTableBase 在网格中追加和删除行

如何解决使用 GridTableBase 在网格中追加和删除行

我在追加和删除行时遇到问题。我的桌子变化很大,必须经常重建,所以这有点棘手。我的所有信息都来自 sql 数据库。我将结果加载到 Pandas DataFrame 中,然后使用它来填充 GridTableBase 类。我现在正在尝试追加和删除行,但无法覆盖该类。我已经能够在某种程度上让它工作,但它的行为很奇怪。出于某种原因,self.table.AppendRows(row) 不起作用并引发错误。原始是 self.table.AppendRow(row),但 AppendRow 不是方法。所以我不得不使用不同的方法。我必须更改一个值才能让 GridTableMessage 意识到发生了变化,这就是我在这里所做的data.iloc[data.shape[0]-1,0] = str(val)

理想情况下,我会从表本身添加/删除行,但我不知道如何做到这一点。我的大部分代码都是从这里 https://github.com/wxWidgets/Phoenix/blob/master/demo/Grid_MegaExample.py 派生出来的,但其中很多对我来说不能正常工作。

截至目前,我可以追加一行,但由于某种原因,即使只有一个添加到 DataFrame 并且 GetNumberRows 返回正确的计数,它也会追加 2。我认为这与我访问表类的方式有关。任何人都可以提供一些清晰度吗?

def rowPopup(self,row,evt):
        """(row,evt) -> display a popup menu when a row label is right clicked"""
        appendID = wx.Window.NewControlId()#wx.NewId()
        deleteID = wx.Window.NewControlId()#wx.NewId()
        x = self.GetRowSize(row)/2
        if not self.GetSelectedRows():
            self.SelectRow(row)
        menu = wx.Menu()
        xo,yo = evt.GetPosition()
        menu.Append(appendID,"Append Row")
        menu.Append(deleteID,"Delete Row(s)")

        def append(event,self=self,row=row):#event,row=row
            global data
            #print("Append")
            #self.table.AppendRows(row)
            dlg = wx.TextEntryDialog(self,'Enter a new Key ID to insert into the ' + str("'") + data.columns[0] + str("'") + ' column.','Insert New Record')
            dlg.SetValue("")
            if dlg.ShowModal() == wx.ID_OK:
            #print('You entered: %s\n' % dlg.GetValue())
                val = dlg.GetValue()
                #data[~pd.isnull(data).all(1)].fillna('')
                #data['tables_id'].apply('(g)'.format)
                data.loc[data.iloc[-1].name + 1,:] = ""
                data.iloc[data.shape[0]-1,0] = str(val)
                self.Reset()
                #print(data)
            #data = data.append(pd.Series(dtype='object'),ignore_index=True)
            #self.data = DataTable(data)
            #data[~pd.isnull(data).all(1)].fillna('')
            #self.data = DataTable(data)
            
        def delete(event,row=row
            global data

            rows = self.GetSelectedRows()
            data.drop(data.index[rows],inplace=True)
            print (data)
            self.Reset()

            #self.table.DeleteRow(row)
            #print(row)
            #print(rows)
        
        #EVT_MENU(self,appendID,append)
        #EVT_MENU(self,deleteID,delete)
        self.Bind(wx.EVT_MENU,append,id=appendID)
        self.Bind(wx.EVT_MENU,delete,id=deleteID)
        self.PopupMenu(menu,wx.Point(round(x),round(yo)))
        menu.Destroy()
class DataTable(gridlib.GridTableBase):
    def __init__(self,data):

        gridlib.GridTableBase.__init__(self)
        self.headerRows = 1
        if data is None:
            data = pd.DataFrame()
        self.data = data
        print("Instance")
        #Store the row and col length to see if table has changed in size
        self._rows = self.GetNumberRows()
        self._cols = self.GetNumberCols()

        self.odd=gridlib.GridCellAttr()
        self.odd.SetBackgroundColour((217,217,217))
        self.even=gridlib.GridCellAttr()
        self.even.SetBackgroundColour((255,255,255))

    def GetAttr(self,col,kind):
        attr = [self.even,self.odd][row % 2]
        attr.IncRef()
        return attr

    def GetNumberRows(self):
        #print("# Rows:",len(self.data))
        return len(self.data)# - 1

    def GetTypeName(self,col):
        #print(wx.grid.GRID_VALUE_STRING)
        return wx.grid.GRID_VALUE_STRING

    def GetNumberCols(self):
        #print("# Cols:",len(self.data.columns)+ 1)
        return len(self.data.columns) + 1
        #return len(self.data.columns) #+ 1

    def IsEmptyCell(self,col):
        return False

    def GetValue(self,col):
        if col == 0:
            try:
                
                return self.data.index[row]
                
            except:
                print("Row,Col(",")","OOB")
                return ""
        else:
            try:
                
                return str(self.data.iloc[row,col - 1])
                
            except:
                print("Row,"OOB")
                return ""
        
       
    def GetColLabelValue(self,col):
        if col == 0:
            if self.data.index.name is None:
                return 'Index'
            else:
                return self.data.index.name
        return self.data.columns[col - 1]

       
    def ResetView(self,grid):
        """
        (wxGrid) -> Reset the grid view.   Call this to
        update the grid if rows and columns have been added or deleted
        """
        print('Old::',self._rows,self._cols)
        print('New::',self.GetNumberRows(),self.GetNumberCols())
        print(data)

        grid.BeginBatch()
        for current,new,delmsg,addmsg in [
            (self._rows,gridlib.GRIDTABLE_NOTIFY_ROWS_DELETED,gridlib.GRIDTABLE_NOTIFY_ROWS_APPENDED),(self._cols,self.GetNumberCols(),gridlib.GRIDTABLE_NOTIFY_COLS_DELETED,gridlib.GRIDTABLE_NOTIFY_COLS_APPENDED),]:
            
            if new < current:
                msg = gridlib.GridTableMessage(self,current-new)
                #grid.ProcesstableMessage(msg)
                self.GetView().ProcesstableMessage(msg)
                print("OvN:",self.GetNumberRows())
                return True
            if new > current:
                msg = gridlib.GridTableMessage(self,addmsg,new-current)
                self.GetView().ProcesstableMessage(msg)
                grid.ProcesstableMessage(msg)
                #self.UpdateValues(grid)

                msg = gridlib.GridTableMessage(self,gridlib.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
                grid.ProcesstableMessage(msg)
                print("OvN:",self.GetNumberRows())
        grid.EndBatch()
           
        self._rows = self.GetNumberRows()
        self._cols = self.GetNumberCols()
        # update the column rendering plugins
        #self._updateColAttrs(grid)
       
        # XXX
        # Okay,this is really stupid,we need to "jiggle" the size
        # to get the scrollbars to recalibrate when the underlying
        # grid changes.
        h,w = grid.GetSize()
        grid.SetSize((h+1,w))
        grid.SetSize((h,w))
        grid.ForceRefresh()
        
        def UpdateValues(self,grid):#self,grid
            """Update all displayed values"""
            # This sends an event to the grid table to update all of the values
            msg = gridlib.GridTableMessage(self,gridlib.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
            grid.table.ProcesstableMessage(msg)

class DataGrid(gridlib.Grid):
    def __init__(self,parent,data,lc,tc): # data
        gridlib.Grid.__init__(self,- 1) #,colnames,-1 # data
       
        self.lc = lc
        self.tc = tc
        self.table = DataTable(data)
      
        self.SetTable(self.table,True)
        self.Bind(gridlib.EVT_GRID_LABEL_RIGHT_CLICK,self.OnLabelRightClicked)
        self.Bind(gridlib.EVT_GRID_CELL_RIGHT_CLICK,self.OnCellRightClick)
        self.Bind(gridlib.EVT_GRID_CELL_CHANGED,self.onCellChanged) #wx.grid
        
    def Reset(self):
        """reset the view based on the data in the table.  Call
        this when rows are added or destroyed"""
        self.table.ResetView(self)

    def OnCellRightClick(self,event):
        print ("OnCellRightClick: (%d,%d)\n" % (event.GetRow(),event.GetCol()))

    def OnLabelRightClicked(self,evt):
        row,col = evt.GetRow(),evt.GetCol()
        if row == -1: print("col")#self.colPopup(col,evt)
        elif col == -1: self.rowPopup(row,evt)

    def rowPopup(self,'Insert New Record')
            dlg.SetValue("")
            if dlg.ShowModal() == wx.ID_OK:
                val = dlg.GetValue()
                #data[~pd.isnull(data).all(1)].fillna('')
                #data['tables_id'].apply('(g)'.format)
                data.loc[data.iloc[-1].name + 1,0] = str(val)
                self.Reset()
                #print(data)
            #self.data = DataTable(data)
            
        def delete(event,inplace=True)
            print (data)
            self.Reset()

           
        self.Bind(wx.EVT_MENU,round(yo)))
        menu.Destroy()
class MainFrame(wx.Frame):
    def __init__(self,data): # (self,data):
        wx.Frame.__init__(self,-1,"Varkey Foundation") #,size=(640,480))
        #Create a panel
        self.p = wx.Panel(self)
        self.Maximize(True)
        
        #Create blank dataframe
        data = pd.DataFrame() #pd.DataFrame(np.random.randint(0,100,size=(200,5)),columns=list('EFGHD')
        #data.reset_index(drop=True,inplace=True)
        self.data = DataTable(data)
        
        self.nb = wx.Notebook(self.p)
        self.p.SetBackgroundColour( wx.Colour( 0,0 ) ) # 38,38,38
        self.nb.SetBackgroundColour(wx.Colour(58,56,56) )
        #self.SetBackgroundColour( wx.Colour( 255,56 ) )

        #create the page windows as children of the notebook
        self.page1 = PageOne(self.nb)
        self.page2 = PageTwo(self.nb)
        self.page3 = PageThree(self.nb)

        # add the pages to the notebook with the label to show on the tab
        self.nb.AddPage(self.page1,"Data")
        self.nb.AddPage(self.page2,"Analyze")
        self.nb.AddPage(self.page3,"Change Log") 

        #CreateFonts
        self.b_font = wx.Font(14,wx.ROMAN,wx.norMAL,wx.BOLD,True)
        self.lbl_font = wx.Font(14,True)
        self.cb_font = wx.Font(11,wx.SCRIPT,wx.ITALIC,True)
        self.h_font = wx.Font(18,wx.DECORATIVE,True)

        #Create username textcontrol <<<<<<<<<<<< Passed to grid class
        self.tc_user =wx.TextCtrl(self.p,value='cmccall95',size = (130,25))
        self.tc_password =wx.TextCtrl(self.p,value='Achilles95',style=wx.TE_PASSWORD | wx.TE_PROCESS_ENTER,25))
        self.tc_password.Bind(wx.EVT_TEXT_ENTER,self.onLogin)
        self.tc_user.SetFont(self.cb_font)
        self.tc_password.SetFont(self.cb_font)

        #Create Change log lstCtrl <<<<<<<<<<<< Passed to grid class
        self.lc_change = wx.ListCtrl(self.p,style = wx.TE_MULTILINE | wx.LC_REPORT | wx.LC_VRULES)
        self.lc_change.InsertColumn(0,"User ID")
        self.lc_change.InsertColumn(1,"Status")
        self.lc_change.InsertColumn(2,"Description")
        self.lc_change.InsertColumn(3,"Date/Time")
        #Set column widths
        self.lc_change.SetColumnWidth(0,75)
        self.lc_change.SetColumnWidth(1,75)
        self.lc_change.SetColumnWidth(2,450)
        self.lc_change.SetColumnWidth(3,125)

        #Create the grid and continue layout 
        self.grid = DataGrid(self.page1,self.lc_change,self.tc_user)

#More layout code...

def onLoadNewData(self,event): #This is how I'm replacing the data in my table class
        global data

        self.Freeze()
        if self.combo_table.GetValue():
            #Connect to db
            self.connect_MysqL()
    
            #Determine db table
            self.getTable()
          
            #Get new data
            sql_query = "SELECT * FROM " + tbl 
            self.cursor.execute(sql_query)
            temp = pd.read_sql(sql_query,con=self.db_con)
            temp.reset_index(drop=True,inplace=True)
            data = temp[~pd.isnull(temp).all(1)].fillna('')
            
            #Create title #if data:
            if not data.empty:
                self.title.SetLabel(str(self.combo_table.GetValue()))
                print(str(self.combo_table.GetValue()))
                self.grid.Destroy()
                self.grid = DataGrid(self.page1,self.tc_user)
                #self.grid.HideCol(0)
                self.grid.AutoSizeColumns()
                
                #Insert grid into existing sizer
                self.p1_sizer.Insert(1,self.grid,1,wx.RIGHT| wx.LEFT|wx.EXPAND,20)
                self.p1_sizer.Layout()
            #RESIZE
            else:
                print("Error:Dataframe is empty")
            self.close_connection()
        else:
            print('CANT BE BLANK')
        self.Thaw()

if __name__ == '__main__':
    import sys
    app = wx.App()
    frame = MainFrame(None,sys.stdout) # (None,sys.stdout)
    frame.Show(True)
    app.MainLoop()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。