0

我正在尝试根据在组合框中选择的表来动态加载带有熊猫数据框的 wxGrid。我可以在初始化时加载网格,但不知道如何刷新 GridTableClass 和网格。现在我正在尝试使用随机数据框进行测试。

class PageOne(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        #wx.StaticText(self, -1, "This is a PageOne object", (20,20))

class PageTwo(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        #wx.StaticText(self, -1, "This is a PageTwo object", (40, 40))


class PageThree(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        #wx.StaticText(self, -1, "This is a PageThree object", (60, 60))

class DataTable(gridlib.GridTableBase):
    def __init__(self, data):

        gridlib.GridTableBase.__init__(self)
        self.data = data
        #self.colnames = colnames

        #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, row, col, kind):
        attr = [self.even, self.odd][row % 2]
        attr.IncRef()
        return attr

    def GetNumberRows(self):
        return len(self.data)

    def GetNumberCols(self):
        return len(self.data.columns) + 1

    def IsEmptyCell(self, row, col):
        return False

    def GetValue(self, row, col):
        #if col == 0:
        #    return None #self.data.index[row]
        return self.data.iloc[row, col-1]

    def SetValue(self, row, col, value):
        self.data.iloc[row, col - 1] = value
    
    def GetColLabelValue(self, col):
        if col == 0:
            return None
            #pass
            #return 'Index' if self.data.index.name is None else self.data.index.name
        return self.data.columns[col - 1] #[col-1]
        #return None
#---------------------------------------------------------------------------
class DataGrid(gridlib.Grid):
    def __init__(self, parent, data): # data
        gridlib.Grid.__init__(self, parent, - 1) #,colnames,-1 # data

        #data = pd.DataFrame(np.random.randint(0,100,size=(200, 5)),columns=list('EFGHD'))
        #data.reset_index(drop=True, inplace=True)
        table = DataTable(data)
        print ("passed")

        # The second parameter means that the grid is to take ownership of the
        # table and will destroy it when done.  Otherwise you would need to keep
        # a reference to it and call it's Destroy method later.
        self.SetTable(table, True)
        self.Bind(gridlib.EVT_GRID_CELL_RIGHT_CLICK, self.OnCellRightClick)

    def OnCellRightClick(self, event):
        print ("OnCellRightClick: (%d,%d)\n" % (event.GetRow(), event.GetCol()))
   
#-------------------------------------------------------------------------------
class MainFrame(wx.Frame):
    def __init__(self, parent, data): # (self, parent, data):
        wx.Frame.__init__(self, parent, -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 = 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, 0 ) ) # 38,38,38
        self.nb.SetBackgroundColour(wx.Colour(58, 56, 56) )
        #self.SetBackgroundColour( wx.Colour( 255, 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")

        #Create the grid and continue layout
        self.grid = DataGrid(self.page1, data)
        #grid.SetReadOnly(5,5, True)
        
        #CreateFonts
        self.b_font = wx.Font(14,wx.ROMAN,wx.NORMAL,wx.BOLD, True)
        self.lbl_font = wx.Font(14,wx.ROMAN,wx.NORMAL,wx.NORMAL, True)
        self.cb_font = wx.Font(11,wx.SCRIPT,wx.ITALIC,wx.NORMAL, True)
        self.h_font = wx.Font(18,wx.DECORATIVE,wx.ITALIC,wx.BOLD, True)
        #Create Title bmp
        ico = wx.Icon('varkey_bmp.bmp', wx.BITMAP_TYPE_ICO) #'varkey_frame.bmp'
        self.SetIcon(ico)

        #Page 1 sizers and widgets
        self.title = wx.StaticText(self.page1,label="TITLE",style = wx.ALIGN_CENTER | wx.ST_NO_AUTORESIZE)
        self.title.SetForegroundColour((255,255,255))
        self.title.SetFont(self.h_font)
        self.p1_sizer = wx.BoxSizer(wx.VERTICAL)
        self.p1_sizer.Add(self.title,0,wx.EXPAND,5)
        self.p1_sizer.Add(self.grid,3,wx.EXPAND | wx.ALL ,25)
        #self.p1_sizer.Add(self.btn_new,-0,wx.ALIGN_CENTER,5)
        self.page1.SetSizer(self.p1_sizer)
        
        #Page 2 sizers and widgets
        self.analyze_grid = gridlib.Grid(self.page2)
        self.analyze_grid.CreateGrid(0, 10)

        self.p2_sizer = wx.BoxSizer(wx.VERTICAL)
        self.p2_sizer.Add(self.analyze_grid,1,wx.EXPAND)
        self.page2.SetSizer(self.p2_sizer)
        
        #Page 3 sizers and widgets
        self.log_grid = gridlib.Grid(self.page3)
        self.log_grid.CreateGrid(0, 9)
        self.log_grid.EnableEditing(False)
       
        self.p3_sizer = wx.BoxSizer(wx.VERTICAL)
        self.p3_sizer.Add(self.log_grid,1,wx.EXPAND)
        self.page3.SetSizer(self.p3_sizer)

        #Create widgets for top sizer
        #Insert Image
        self.staticbitmap = wx.StaticBitmap(self.p)
        self.staticbitmap.SetBitmap(wx.Bitmap('varkey_logo2.jpg'))
        self
        self.lbl_user = wx.StaticText(self.p,label="Username:")
        self.lbl_password = wx.StaticText(self.p,label="Password:")
        self.lbl_interaction = wx.StaticText(self.p,label="Interaction:")
        self.lbl_table = wx.StaticText(self.p,label="Table:")
        #SetForground colors
        self.lbl_user.SetForegroundColour((255,255,255))
        self.lbl_password.SetForegroundColour((255,255,255))
        self.lbl_interaction.SetForegroundColour((255,255,255))
        self.lbl_table.SetForegroundColour((255,255,255))

        #Set Fonts
        self.lbl_user.SetFont(self.lbl_font)
        self.lbl_password.SetFont(self.lbl_font)
        self.lbl_interaction.SetFont(self.lbl_font)
        self.lbl_table.SetFont(self.lbl_font)

        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,size = (130,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)

        self.btn_login = wx.Button(self.p,label="Login", size=(105,30))
        self.btn_login.SetBackgroundColour(wx.Colour(198, 89, 17))
        self.btn_login.SetFont(self.b_font)
        self.btn_login.Bind(wx.EVT_BUTTON, self.onLogin) #connect_mysql

        self.btn_logout = wx.Button(self.p,label="Logout",size=(105,30))
        self.btn_logout.SetBackgroundColour(wx.Colour(192,0,0))
        self.btn_logout.SetFont(self.b_font)
        #self.btn_logout.Bind(wx.EVT_BUTTON, self.onLogout)


        self.combo_interaction = wx.ComboBox(self.p, size = (160,25),style = wx.CB_READONLY | wx.CB_SORT | wx.CB_SORT)
        #self.combo_interaction.Bind(wx.EVT_COMBOBOX, self.onComboInteraction)
        self.combo_table = wx.ComboBox(self.p, size = (160,25),style = wx.CB_READONLY | wx.CB_SORT | wx.CB_SORT)
        #self.combo_table.Bind(wx.EVT_COMBOBOX, self.onHideCommands)
        self.combo_interaction.SetFont(self.cb_font)
        self.combo_table.SetFont(self.cb_font)

        #self.combo_table.Bind(wx.EVT_COMBOBOX         ,self.OnComboTable)
        self.btn_load  = wx.Button(self.p,label="Load Table", size=(105,30))
        self.btn_load.SetBackgroundColour(wx.Colour(31, 216, 6))
        self.btn_load.SetFont(self.b_font)
        #self.btn_load.Bind(wx.EVT_BUTTON, self.onLoadData)
        self.btn_load.Bind(wx.EVT_BUTTON, self.test_return)

        self.lc_change = wx.ListCtrl(self.p,-1,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 Filler text
        self.lbl_filler = wx.StaticText(self.p,label="",size = (125,20))
        #Create FlexGridSizers(For top half)
        self.left_fgs = wx.FlexGridSizer(3,4,25,15)
        self.left_fgs.AddMany([(self.lbl_user,1,wx.ALIGN_LEFT | wx.LEFT,15),(self.tc_user,1,wx.EXPAND),(self.lbl_interaction,1,wx.ALIGN_RIGHT|wx.RIGHT, 10),(self.combo_interaction,1,wx.EXPAND),
                               (self.lbl_password,1,wx.ALIGN_LEFT| wx.LEFT,15),(self.tc_password,1,wx.EXPAND),(self.lbl_table,1,wx.ALIGN_RIGHT|wx.RIGHT, 10),(self.combo_table),
                               (self.btn_login,2,wx.EXPAND),(self.btn_logout,1,wx.EXPAND),(self.lbl_filler,1,wx.EXPAND),(self.btn_load,1)])

        #Create Top Sizer 
        self.top_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.top_sizer.Add(self.left_fgs,proportion = 1, flag = wx.ALL|wx.EXPAND,border = 30)
        self.top_sizer.Add(self.staticbitmap,2,wx.TOP | wx.RIGHT, border = 40) #30
        self.top_sizer.Add(self.lc_change,2,wx.RIGHT|wx.EXPAND ,30)

        #create Bottom Sizer
        self.bottom_sizer = wx.BoxSizer(wx.VERTICAL)
        self.bottom_sizer.Add(self.nb,proportion = 5, flag = wx.LEFT |wx.RIGHT | wx.EXPAND,border = 30)
        
        self.mainsizer = wx.BoxSizer(wx.VERTICAL)
        self.mainsizer.Add(self.top_sizer,proportion = 0, flag = wx.ALL|wx.EXPAND,border = 5)
        self.mainsizer.Add(self.bottom_sizer,proportion = 1,flag = wx.ALL|wx.EXPAND,border = 5)
        #self.mainsizer.Add(self.status_sizer,proportion =0,flag = wx.BOTTOM|wx.ALIGN_CENTER_HORIZONTAL, border = 15)
        self.p.SetSizerAndFit(self.mainsizer)

    
    def test_reload(self, event):
        data = pd.DataFrame() #pd.DataFrame(np.random.randint(0,100,size=(200, 5)),columns=list('EFGHD')
        data = 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.table.data = self.data
        self.grid.Refresh()

#Some more functions.......

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

我尝试了该功能的许多不同变体,但无法理解它应该如何工作。根据我的理解,我应该先调用表格然后再调用网格来刷新。

def test_reload(self, event):
        data = pd.DataFrame() #pd.DataFrame(np.random.randint(0,100,size=(200, 5)),columns=list('EFGHD')
        data = pd.DataFrame(np.random.randint(0,100,size=(200, 5)),columns=list('EFGHD'))
        self.table.data = self.data
        self.grid.Refresh()
4

1 回答 1

0

我设法找到了解决方案。希望这可以帮助其他人。

要重新加载网格,我首先创建新数据。然后我销毁网格,创建一个新网格,并将其插入旧网格的位置。然后您必须调用 Layout()。Freeze() 和 Thaw() 方法用于防止屏幕闪烁。

def test_reload(self, event):

        self.Freeze()

        #Create new data
        data = pd.DataFrame(np.random.randint(0,100,size=(40000, 5)),columns=list('EFGHD'))
        

        #Destroy and create grid with new data assigned
        self.grid.Destroy()
        self.grid = DataGrid(self.page1, data)

        #Insert grid into existing sizer
        self.p1_sizer.Insert(1,self.grid,1,wx.RIGHT| wx.LEFT|wx.EXPAND, 20)
        self.p1_sizer.Layout()

        self.Thaw()

我确信那里有更好的方法,但这有效并且是即时的。

于 2021-07-09T04:31:16.167 回答