I am having trouble with the layout of the frame. The data is stored in a dataframe, and the intent is to be able to browse for a file and select that file from a ComboBox. I am trying to display the contents in the frame. The first time it works correctly. The second time it just adds it to the vertical sizer under the previous data. I need to delete or replace the data. The data displayed should be the the updated dataframe. I have tried the .Destroy() on the GridSizer, the Vertical BoxSizer, I've tried adding more sizers combined with the Freeze() and Thaw() methods, and adding a new Panel Class. Nothing seems to work.
I am also having a difficult time getting the StaticText boxes in the GridSizer to adjust to fit the screen. What am I doing wrong?
def onOpenFile(self, event):
"""
Create and show the Open FileDialog
"""
global column_names
global df_lookup_options
global options_ID
#self.Freeze
#Dialog 1
dlg1 = wx.FileDialog(
self, message="Browse Files",
defaultFile="",
wildcard=wildcard,
style=wx.FD_OPEN | wx.FD_MULTIPLE | wx.FD_CHANGE_DIR)
if dlg1.ShowModal() == wx.ID_OK:
paths = dlg1.GetPaths()
for path in paths:
filepath = path.replace("\\","/")
xls = xlrd.open_workbook(filepath, on_demand=True)
sheet_options = xls.sheet_names()
dlg1.Destroy()
#Dialog 2
dlg2 = wx.SingleChoiceDialog(None,"Select
Worksheet","Worksheet",sheet_options,wx.CHOICEDLG_STYLE)
if dlg2.ShowModal() == wx.ID_OK:
sel_sheet = dlg2.GetStringSelection()
sel_index = dlg2.GetSelection()
#Get Count of Worksheet Rows and Colums
wb = xlrd.open_workbook(filepath)
sheet = wb.sheet_by_index(sel_index)
row_count = sheet.nrows
column_count = sheet.ncols
df_rows = len(df_lookup_options.index)
dlg2.Destroy()
#Dialog 3
dlg3 = wx.TextEntryDialog(None,"Enter Unique ID","Unique ID")
if dlg3.ShowModal() == wx.ID_OK:
unique_id = dlg3.GetValue()
dlg3.Destroy()
#Dialog 4
dlg4 = wx.TextEntryDialog(None,"Enter Header Row","Header Row")
if dlg4.ShowModal() == wx.ID_OK:
header_row = dlg4.GetValue()
dlg4.Destroy()
#Dialog 5
dlg5 = wx.TextEntryDialog(None,"Enter First Data Column #","Start Column")
if dlg5.ShowModal() == wx.ID_OK:
column_start = dlg5.GetValue()
dlg5.Destroy()
#Add Variables to Dataframe Row
df_lookup_options = df_lookup_options.append({'Unique
ID':unique_id,'Worksheet':sel_sheet,'Index':sel_index,'Filepath':filepath,
'Rows':row_count,'Columns':column_count,'Header
Row':header_row,
'Start Column':column_start},ignore_index=True)
options_ID = df_lookup_options['Unique ID'].tolist()
self.combo1.Clear()
self.combo1.Append(options_ID)
#Get Dataframe Size
df_row = len(df_lookup_options)
df_col = len(df_lookup_options.columns)
#Display Source info
#self.fgs.Destroy()
#self.vbox = wx.BoxSizer(wx.VERTICAL)
self.fgs = wx.FlexGridSizer(df_row + 1,df_col,2,25)
#Create Headers
for i in column_names:
self.fgs.Add(wx.StaticText(self, label = i), proportion=1, flag=wx.ALIGN_CENTER_VERTICAL
| wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, border=5)
self.Layout
##
for r in range(df_row):
for y in range(df_col):
for c in range(1,df_col + 1):
i = df_lookup_options.iloc[r, y]
txt = str(i)
self.fgs.Add(wx.StaticText(self, label = txt), proportion=1, flag=wx.ALL | wx.EXPAND)
self.vbox.Add(self.fgs, proportion=1, flag=wx.ALL|wx.EXPAND, border=10)
self.SetSizer(self.vbox)
self.Fit()
self.Layout()
#self.Thaw
Complete Code:
import wx
import xlrd
import pandas as pd
wildcard = "Excel Files(*.xlsm; *.xlsx)|*.xlsm;*.xlsx|" \
"All files (*.*)|*.*"
#"Python source (*.py; *.pyc)|*.py;*.pyc|" \
#"All files (*.*)|*.*"
column_names = ['Unique ID','Worksheet','Index','Filepath','Rows','Columns','Header Row','Start
Column']
df_lookup_options = pd.DataFrame(columns=column_names)
df_lookup = pd.DataFrame()
options_ID = []
source_selection = ""
########################################################################
class MyForm(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY,
"Set Source Files")
self.vbox = wx.BoxSizer(wx.VERTICAL)
#self.vbox2 = wx.BoxSizer(wx.VERTICAL)
#self.hbox = wx.BoxSizer(wx.HORIZONTAL)
self.btn = wx.Button(self, label="Add Source File")
self.btn.Bind(wx.EVT_BUTTON, self.onOpenFile)
self.combo1 = wx.ComboBox(self, choices=options_ID)
self.combo1.Bind(wx.EVT_COMBOBOX, self.onCombo)
self.combo1.SetHint('-Choose Source-')
self.vbox.Add(self.btn, flag=wx.EXPAND|wx.TOP|wx.BOTTOM, border=4)
self.vbox.Add(self.combo1, flag=wx.EXPAND|wx.TOP|wx.BOTTOM, border=4)
#self.hbox.Add(self.fgs1, flag=wx.EXPAND|wx.TOP|wx.BOTTOM, border=4)
#self.vbox.Add(self.hbox, flag=wx.EXPAND|wx.TOP|wx.BOTTOM, border=4)
#self.vbox.Add(self.fgs, flag=wx.EXPAND|wx.TOP|wx.BOTTOM, border=4)
self.SetSizer(self.vbox)
#----------------------------------------------------------------------
def onOpenFile(self, event):
"""
Create and show the Open FileDialog
"""
global column_names
global df_lookup_options
global options_ID
#self.Freeze
#Dialog 1
dlg1 = wx.FileDialog(
self, message="Browse Files",
defaultFile="",
wildcard=wildcard,
style=wx.FD_OPEN | wx.FD_MULTIPLE | wx.FD_CHANGE_DIR)
if dlg1.ShowModal() == wx.ID_OK:
paths = dlg1.GetPaths()
for path in paths:
filepath = path.replace("\\","/")
xls = xlrd.open_workbook(filepath, on_demand=True)
sheet_options = xls.sheet_names()
dlg1.Destroy()
#Dialog 2
dlg2 = wx.SingleChoiceDialog(None,"Select
Worksheet","Worksheet",sheet_options,wx.CHOICEDLG_STYLE)
if dlg2.ShowModal() == wx.ID_OK:
sel_sheet = dlg2.GetStringSelection()
sel_index = dlg2.GetSelection()
#Get Count of Worksheet Rows and Colums
wb = xlrd.open_workbook(filepath)
sheet = wb.sheet_by_index(sel_index)
row_count = sheet.nrows
column_count = sheet.ncols
df_rows = len(df_lookup_options.index)
dlg2.Destroy()
#Dialog 3
dlg3 = wx.TextEntryDialog(None,"Enter Unique ID","Unique ID")
if dlg3.ShowModal() == wx.ID_OK:
unique_id = dlg3.GetValue()
dlg3.Destroy()
#Dialog 4
dlg4 = wx.TextEntryDialog(None,"Enter Header Row","Header Row")
if dlg4.ShowModal() == wx.ID_OK:
header_row = dlg4.GetValue()
dlg4.Destroy()
#Dialog 5
dlg5 = wx.TextEntryDialog(None,"Enter First Data Column #","Start Column")
if dlg5.ShowModal() == wx.ID_OK:
column_start = dlg5.GetValue()
dlg5.Destroy()
#Add Variables to Dataframe Row
df_lookup_options = df_lookup_options.append({'Unique
ID':unique_id,'Worksheet':sel_sheet,'Index':sel_index,'Filepath':filepath,
'Rows':row_count,'Columns':column_count,'Header
Row':header_row,
'Start Column':column_start},ignore_index=True)
options_ID = df_lookup_options['Unique ID'].tolist()
self.combo1.Clear()
self.combo1.Append(options_ID)
#Get Dataframe Size
df_row = len(df_lookup_options)
df_col = len(df_lookup_options.columns)
#Display Source info
#self.fgs.Destroy()
#self.vbox = wx.BoxSizer(wx.VERTICAL)
self.fgs = wx.FlexGridSizer(df_row + 1,df_col,2,25)
#Create Headers
for i in column_names:
self.fgs.Add(wx.StaticText(self, label = i), proportion=1, flag=wx.ALIGN_CENTER_VERTICAL
| wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, border=5)
self.Layout
##
for r in range(df_row):
for y in range(df_col):
for c in range(1,df_col + 1):
i = df_lookup_options.iloc[r, y]
txt = str(i)
self.fgs.Add(wx.StaticText(self, label = txt), proportion=1, flag=wx.ALL | wx.EXPAND)
self.vbox.Add(self.fgs, proportion=1, flag=wx.ALL|wx.EXPAND, border=10)
self.SetSizer(self.vbox)
self.Fit()
self.Layout()
#self.Thaw
def onCombo(self, event):
global df_lookup
self.source_selection = self.combo1.GetSelection()
file_name = df_lookup_options.iloc[self.source_selection, 3]
sheet_name = df_lookup_options.iloc[self.source_selection, 1]
start_header_row = int(df_lookup_options.iloc[self.source_selection, 6]) - 1
start_column = int(df_lookup_options.iloc[self.source_selection, 7]) - 1
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()
Related
I am trying to dynamically load a wxGrid with a pandas Dataframe depending on what table is selected in the combobox. I can get the grid to load on intialization, but can't figure out how to get refresh the GridTableClass and grid. Right now I am trying to test with a random Dataframe.
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()
I've tried many different variations of the function and can't understand how this should work. From my understanding, I should the table and then call the grid to refresh.
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()
I managed to find a solution. Hopefully this helps someone else out.
To reload the grid, I first create new data. Then I destroy the grid, create a new grid, and insert it in place of the old grid. You must then call Layout(). The Freeze() and Thaw() methods are to prevent screen flickering.
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()
I'm sure there is a better method out there, but this works and is instant.
In the part of the code included between ################ Code ######### I try to do a control with if but doesn't work.
I would like that when the variable 'ts' is equal to the variable 'prova' the line(item) in the same list ctrl becomes red. For all item which I insert in the ctrl list. Thanks so much!
import wx
import wx.gizmos as gizmos
import time
import datetime
from datetime import timedelta
class CWindow(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, style = wx.DEFAULT_FRAME_STYLE & ~ wx.CLOSE_BOX ^ wx.MAXIMIZE_BOX ^ wx.RESIZE_BORDER, size=(600,500))
dataCorrente = datetime.datetime.now()
self.Panel = wx.Panel(self, -1)
self.index = 0
self.CTesto = wx.TextCtrl(self.Panel, 1, pos=(10,40), style=wx.TE_PROCESS_ENTER)
self.CTesto.Bind(wx.EVT_TEXT_ENTER,self.add_line)
self.list_ctrl = wx.ListCtrl(self.Panel, pos=(10,90),size=(-1,300),style=wx.LC_REPORT|wx.BORDER_SUNKEN)
self.list_ctrl.InsertColumn(0, 'Name')
self.list_ctrl.InsertColumn(1, 'Time START')
self.list_ctrl.InsertColumn(2, 'Time FINISH', width=100)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.list_ctrl, 0, wx.ALL|wx.EXPAND, 5)
self.led = gizmos.LEDNumberCtrl(self.Panel, -1, pos = (350,25), size = (200,50), style = gizmos.LED_ALIGN_CENTER)
self.led.SetBackgroundColour("#c0c0c0")
self.led.SetForegroundColour("black")
self.OnTimer(None)
self.timer = wx.Timer(self, -1)
self.timer.Start(1000)
self.Bind(wx.EVT_TIMER, self.OnTimer)
style = gizmos.LED_ALIGN_CENTER
def OnTimer(self, event):
current = time.localtime(time.time())
global ts
ts = time.strftime("%H:%M:%S", current)
self.led.SetValue(ts)
#print (ts) # In Loop it's OK
############################################################################################################################
if ts == prova:
self.list_ctrl.SetItemBackgroundColour(self.index, wx.RED)
############################################################################################################################
def add_line(self,event):
val = str(self.CTesto.GetValue())
if val== '':
msg = wx.MessageDialog(self, "Error", "Error", wx.OK| wx.ICON_ERROR)
msg.ShowModal()
msg.Destroy()
else:
dataCorrente = datetime.datetime.now()
oraAttuale =(dataCorrente.strftime("%H:%M:%S"))
plus = (datetime.datetime.strptime(oraAttuale, "%H:%M:%S") + datetime.timedelta(minutes=1))
global plus2
plus2 = plus.strftime("%H:%M:%S")
self.list_ctrl.InsertItem(self.index, val)
self.list_ctrl.SetItem(self.index, 1, oraAttuale)
self.list_ctrl.SetItem(self.index, 2, str(plus2))
self.index += 1
InsVal = (val + " - " + oraAttuale + " - " + plus2 + '\n')
self.CTesto.Clear()
print (InsVal)
prova = InsVal[-9:]
app = wx.App()
frame = CWindow(None, -1, "Example")
frame.Show()
frame.Center()
app.MainLoop()
repr() is your friend in this question.
print(repr(self.prova)) would reveal that it contains a newline character, so that needs to be stripped off.
Also note that the ListCtrl index is zero based, so to apply the colour, you have to use index - 1.
With these minor adjustments your code works, as I hope you planned it to.
import wx
import wx.gizmos as gizmos
import time
import datetime
from datetime import timedelta
class CWindow(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, style = wx.DEFAULT_FRAME_STYLE & ~ wx.CLOSE_BOX ^ wx.MAXIMIZE_BOX ^ wx.RESIZE_BORDER, size=(600,500))
dataCorrente = datetime.datetime.now()
self.Panel = wx.Panel(self, -1)
self.index = 0
self.prova = {}
self.ts = ""
self.CTesto = wx.TextCtrl(self.Panel, 1, pos=(10,40), style=wx.TE_PROCESS_ENTER)
self.CTesto.Bind(wx.EVT_TEXT_ENTER,self.add_line)
self.list_ctrl = wx.ListCtrl(self.Panel, pos=(10,90),size=(-1,300),style=wx.LC_REPORT|wx.BORDER_SUNKEN)
self.list_ctrl.InsertColumn(0, 'Name')
self.list_ctrl.InsertColumn(1, 'Time START')
self.list_ctrl.InsertColumn(2, 'Time FINISH', width=100)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.list_ctrl, 0, wx.ALL|wx.EXPAND, 5)
self.led = gizmos.LEDNumberCtrl(self.Panel, -1, pos = (350,25), size = (200,50), style = gizmos.LED_ALIGN_CENTER)
self.led.SetBackgroundColour("#c0c0c0")
self.led.SetForegroundColour("black")
self.OnTimer(None)
self.timer = wx.Timer(self, -1)
self.timer.Start(1000)
self.Bind(wx.EVT_TIMER, self.OnTimer)
style = gizmos.LED_ALIGN_CENTER
def OnTimer(self, event):
current = time.localtime(time.time())
self.ts = time.strftime("%H:%M:%S", current)
self.led.SetValue(self.ts)
############################################################################################################################
if self.ts in self.prova:
self.list_ctrl.SetItemBackgroundColour(self.prova.pop(self.ts), wx.RED)
############################################################################################################################
def add_line(self,event):
val = str(self.CTesto.GetValue())
if val== '':
msg = wx.MessageDialog(self, "Error", "Error", wx.OK| wx.ICON_ERROR)
msg.ShowModal()
msg.Destroy()
else:
dataCorrente = datetime.datetime.now()
oraAttuale =(dataCorrente.strftime("%H:%M:%S"))
plus = (datetime.datetime.strptime(oraAttuale, "%H:%M:%S") + datetime.timedelta(minutes=1))
plus2 = plus.strftime("%H:%M:%S")
if plus2 in self.prova:
msg = wx.MessageDialog(self, "Duplicated Time", "Error", wx.OK| wx.ICON_ERROR)
msg.ShowModal()
msg.Destroy()
return
self.list_ctrl.InsertItem(self.index, val)
self.list_ctrl.SetItem(self.index, 1, oraAttuale)
self.list_ctrl.SetItem(self.index, 2, str(plus2))
self.index += 1
InsVal = (val + " - " + oraAttuale + " - " + plus2 + '\n')
self.CTesto.Clear()
self.prova[plus2] = self.index -1
app = wx.App()
frame = CWindow(None, -1, "Example")
frame.Show()
frame.Center()
app.MainLoop()
Edit:
If you want to test for all of the entries, turning them red as they occur, you will have to change the nature of prova.
One way would be to make prova a dictionary and use the edited code above.
This provides a method to prevent duplicate entries and a simple method for deleting entries in the dictionary prova reducing the amount of checking required. In this way the code can run continuously for days without hitting duplicates. The dictionary entries are the Finish time and the listctrl's index value, used to perform the highlighting.
The act of deleting the dictionary entry (pop), returns the index number for the highlight.
1) It is possible to insert somehow the button in each line of the certain column of object wx.ListCtrl?
2) Why is it possible to edit the value of a string only in the first column? Initializing wx.ListCtrl:
self.m_listCtrl_number = wx.ListCtrl(self.panel, wx.ID_ANY, wx.DefaultPosition, (450, 80),
wx.LC_REPORT | wx.BORDER_SUNKEN | wx.LC_EDIT_LABELS | wx.LC_SINGLE_SEL)
self.bsizer_textCtrl.Add(self.m_listCtrl_number, 0, wx.ALL, 5)
self.m_listCtrl_number.InsertColumn(0, 'Min', format=wx.LIST_FORMAT_CENTER, width=wx.LIST_AUTOSIZE)
self.m_listCtrl_number.InsertColumn(1, 'Max', format=wx.LIST_FORMAT_CENTER, width=wx.LIST_AUTOSIZE)
self.m_listCtrl_number.InsertColumn(2, 'Fill', format=wx.LIST_FORMAT_CENTER, width=wx.LIST_AUTOSIZE_USEHEADER)
Adding an item:
self.m_listCtrl_number.InsertItem(self.index_numer, '0')
self.m_listCtrl_number.SetItem(self.index_numer, 1, '1')
self.m_listCtrl_number.SetItem(self.index_numer, 2, 'qwerty') # fixme Button!!!
self.index_numer += 1
You will have to use ultimatelistctrl.
Here is a hacked version of one of the demonstration programs:
import wx
from wx.lib.agw import ultimatelistctrl as ULC
class TestPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
boldfont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
boldfont.SetWeight(wx.BOLD)
boldfont.SetPointSize(12)
self.ulc = ULC.UltimateListCtrl(self, agwStyle = wx.LC_REPORT
| wx.LC_VRULES
| wx.LC_HRULES
| ULC.ULC_HAS_VARIABLE_ROW_HEIGHT)
info = ULC.UltimateListItem()
info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT | ULC.ULC_MASK_CHECK
info._image = []
info._format = 0
info._kind = 1
info._text = "Artist Name"
self.ulc.InsertColumnInfo(0, info)
info = ULC.UltimateListItem()
info._format = wx.LIST_FORMAT_RIGHT
info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT | ULC.ULC_MASK_FONT
info._image = []
info._text = "Title"
info._font = boldfont
self.ulc.InsertColumnInfo(1, info)
info = ULC.UltimateListItem()
info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT
info._format = 0
info._text = "Genre"
info._font = font
info._image = []
self.ulc.InsertColumnInfo(2, info)
self.button1 = wx.Button(self.ulc, -1, "Button1")
self.button2 = wx.Button(self.ulc, -1, "Button2")
self.button3 = wx.Button(self.ulc, -1, "Button3")
index = self.ulc.InsertStringItem(3, " ")
self.ulc.SetItemWindow(index, 0, self.button1)
self.ulc.SetItemWindow(index, 1, self.button2)
self.ulc.SetItemWindow(index, 2, self.button3)
self.Bind(wx.EVT_BUTTON, self.OnButton)
self.ulc.InsertStringItem(0, "Newsboys")
self.ulc.SetStringItem(0, 1, "Go")
self.ulc.SetStringItem(0, 2, "Rock")
self.ulc.InsertStringItem(1, "Puffy")
self.ulc.SetStringItem(1, 1, "Bring It!")
self.ulc.SetStringItem(1, 2, "Pop")
self.ulc.InsertStringItem(2, "Family Force 5")
self.ulc.SetStringItem(2, 1, "III")
self.ulc.SetStringItem(2, 2, "Crunk")
self.ulc.SetColumnWidth(0, 150)
self.ulc.SetColumnWidth(1, 200)
self.ulc.SetColumnWidth(2, 100)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.ulc, 1, wx.EXPAND)
self.SetSizer(sizer)
def OnButton(self,event):
b= event.GetEventObject()
print(b.GetLabel(),"pressed")
########################################################################
class TestFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="MvP UltimateListCtrl Demo")
panel = TestPanel(self)
self.Show()
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.App()
frame = TestFrame()
app.MainLoop()
I am using a Panel within a Frame to display images (the GUI need to switch between multiple panels and hence the hierarchy). As images should be displayed in native size I used ScrolledWindow as the panel parent. The scrolls do appear and work, but it causes the Panel to collapse to minimum size and it needs to be resized using drag&drop every time.
Is there a way around this?
Below is a reduced version of the code, which shows the problem:
import os
import wx
from wx.lib.pubsub import pub
class Edit_Panel(wx.PyScrolledWindow):
def __init__(self, parent):
super(Edit_Panel, self).__init__(parent)
# Display size
width, height = wx.DisplaySize()
self.photoMaxSize = height - 500
# Loaded image
self.loaded_image = None
# Icons
self.open_icon_id = 500
# Generate panel
self.layout()
def layout(self):
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
divider = wx.StaticLine(self, -1, style = wx.LI_HORIZONTAL)
self.main_sizer.Add(divider, 0, wx.ALL | wx.EXPAND)
self.toolbar = self.init_toolbar()
self.main_sizer.Add(self.toolbar, 0, wx.ALL)
img = wx.EmptyImage(self.photoMaxSize, self.photoMaxSize)
self.image_control = wx.StaticBitmap(self, wx.ID_ANY,
wx.BitmapFromImage(img))
self.main_sizer.Add(self.image_control, 0, wx.ALL | wx.CENTER, 5)
self.image_label = wx.StaticText(self, -1, style = wx.ALIGN_CENTRE)
self.main_sizer.Add(self.image_label, 0, wx.ALL | wx.ALIGN_CENTRE, 5)
self.SetSizer(self.main_sizer)
fontsz = wx.SystemSettings.GetFont(wx.SYS_SYSTEM_FONT).GetPixelSize()
self.SetScrollRate(fontsz.x, fontsz.y)
self.EnableScrolling(True, True)
def init_toolbar(self):
toolbar = wx.ToolBar(self)
toolbar.SetToolBitmapSize((16, 16))
open_ico = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, (16, 16))
open_tool = toolbar.AddSimpleTool(self.open_icon_id, open_ico, "Open", "Open an Image Directory")
handler = self.on_open_reference
self.Bind(event = wx.EVT_MENU, handler = handler, source = open_tool)
toolbar.Realize()
return toolbar
def on_open_reference(self, event, wildcard = None):
if wildcard is None:
wildcard = self.get_wildcard()
defaultDir = '~/'
dbox = wx.FileDialog(self, "Choose an image to display", defaultDir = defaultDir, wildcard = wildcard, style = wx.OPEN)
if dbox.ShowModal() == wx.ID_OK:
file_name = dbox.GetPath()
# load image
self.load_image(image = file_name)
dbox.Destroy()
def get_wildcard(self):
wildcard = 'Image files (*.jpg;*.png;*.bmp)|*.png;*.bmp;*.jpg;*.jpeg'
return wildcard
def load_image(self, image):
self.loaded_image = image
# Load image
img = wx.Image(image, wx.BITMAP_TYPE_ANY)
# Label image name
image_name = os.path.basename(image)
self.image_label.SetLabel(image_name)
# scale the image, preserving the aspect ratio
scale_image = True
if scale_image:
W = img.GetWidth()
H = img.GetHeight()
if W > H:
NewW = self.photoMaxSize
NewH = self.photoMaxSize * H / W
else:
NewH = self.photoMaxSize
NewW = self.photoMaxSize * W / H
img = img.Scale(NewW, NewH)
self.image_control.SetBitmap(wx.BitmapFromImage(img))
# Render
self.main_sizer.Layout()
self.main_sizer.Fit(self)
self.Refresh()
pub.sendMessage("resize", msg = "")
class Viewer_Frame(wx.Frame):
def __init__(self, parent, id, title):
super(Viewer_Frame, self).__init__(parent = parent, id = id, title = title)
# Edit panel
self.edit_panel = Edit_Panel(self)
# Default panel
self.main_panel = self.edit_panel
# Render frame
self.render_frame()
# Subscription to re-render
pub.subscribe(self.resize_frame, ("resize"))
def render_frame(self):
# Main Sizer
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
# Add default sizer
self.main_sizer.Add(self.main_panel, 1, wx.EXPAND)
# Render
self.SetSizer(self.main_sizer)
self.Show()
self.main_sizer.Fit(self)
self.Center()
def resize_frame(self, msg):
self.main_sizer.Fit(self)
if __name__ == "__main__":
app = wx.App(False)
frame = Viewer_Frame(parent = None, id = -1, title = 'Toolkit')
app.MainLoop()
You're calling Fit(), so you're explicitly asking the panel to fit its contents, but you don't specify the min/best size of this contents anywhere (AFAICS, there is a lot of code here, so I could be missing something).
If you want to use some minimal size for the panel, just set it using SetMinSize().
Am working on a project where I have to import CSV files into wx.Grid for further manipulations.
I have searched and found a useful way here http://wxpython-users.1045709.n5.nabble.com/new-to-the-list-opening-a-text-file-in-a-grid-using-splitterwindows-td2373808.html
Now my CSV never seems to display on my screen frame at all (as per the code below)? Any way around this?
csv1.py is the GUI
class MyFrame3 ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 900,600 ), style = wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.TAB_TRAVERSAL )
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
Sizer1 = wx.BoxSizer( wx.HORIZONTAL )
Sizer1.SetMinSize( wx.Size( 0,0 ) )
self.Right_Panel = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
RightSizer = wx.BoxSizer( wx.VERTICAL )
self.Right_Panel.SetSizer( RightSizer )
self.Right_Panel.Layout()
RightSizer.Fit( self.Right_Panel )
Sizer1.Add( self.Right_Panel, 1, wx.EXPAND |wx.ALL, 5 )
self.Left_Panel = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
LeftSizer = wx.BoxSizer( wx.VERTICAL )
self.ImportButton = wx.Button( self.Left_Panel, wx.ID_ANY, u"Import CSV File", wx.DefaultPosition, wx.DefaultSize, 0 )
LeftSizer.Add( self.ImportButton, 0, wx.ALL, 5 )
self.Left_Panel.SetSizer( LeftSizer )
self.Left_Panel.Layout()
LeftSizer.Fit( self.Left_Panel )
Sizer1.Add( self.Left_Panel, 0, wx.EXPAND |wx.ALL, 5 )
self.SetSizer( Sizer1 )
self.Layout()
self.menubar = wx.MenuBar( 0 )
self.fileMenu = wx.Menu()
self.importMenu = wx.MenuItem( self.fileMenu, wx.ID_ANY, u"Import", wx.EmptyString, wx.ITEM_NORMAL )
self.fileMenu.AppendItem( self.importMenu )
self.menubar.Append( self.fileMenu, u"&File" )
self.SetMenuBar( self.menubar )
self.Centre( wx.BOTH )
# Connect Events
self.ImportButton.Bind( wx.EVT_BUTTON, self.ImportFunc )
self.Bind( wx.EVT_MENU, self.ImportFunc, id = self.importMenu.GetId() )
class csv_view(wx.App):
def OnInit(self):
self.frame=MyFrame3(None, -1, 'PyStereo', size=(900,600))
self.SetTopWindow(self.frame)
return True
csv2.py is the running script
#!/usr/bin/python
# -*- coding: utf-8 -*-
import wx
import os
import numpy as np
import sys, csv
import wx.grid
from csv1 import MyFrame3, csv_view
class MyFrame(MyFrame3):
def __init__(self, parent, size = wx.Size(900,600)):
MyFrame3.__init__ (self, parent)
self.dirname = os.getcwd()
# Import/Open CSV
def ImportFunc( self, event ):
'''THIS IMPORTED CSV WILL NEVER EXPAND TO FIT INTO THE FRAME, PLEASE HELP?'''
dlg=wx.FileDialog(self, 'Choose a file', self.dirname, '','CSV files (*.csv)|*.csv|All files(*.*)|*.*',wx.OPEN)
if dlg.ShowModal() == wx.ID_OK:
self.dirname=dlg.GetDirectory()
self.filename=os.path.join(self.dirname,dlg.GetFilename())
self.file=file(self.filename, 'r')
#check for file format with sniffer
dialect = csv.Sniffer().sniff(self.file.read(1024))
self.file.seek(0)
csvfile=csv.reader(self.file,dialect)
filedata = [] #put contents of csvfile into a list
filedata.extend(csvfile)
self.file.seek(0)
#grab a sample and see if there is a header
sample=self.file.read(2048)
self.file.seek(0)
if csv.Sniffer().has_header(sample): #if there is a header
colnames=csvfile.next() # label columns from first line
datalist=[] # create a list without the header
datalist.extend(filedata[1:len(filedata)]) #append data without header
else:
row1=csvfile.next() #if there is NO header
colnames=[]
for i in range(len(row1)):
colnames.append('col_%d' % i) # label columns as col_1, col_2, etc
self.file.seek(0)
datalist=filedata #append data to datalist
self.file.close()
self.createGrid(datalist, colnames)
#create the grid
def createGrid(self, datalist, colnames):
if getattr(self, 'grid', 0): self.grid.Destroy()
self.grid=wx.grid.Grid(self, 0)
self.grid.CreateGrid(len(datalist), len(colnames)) #create grid, same size as file (rows, cols)
#fill in headings
for i in range(len(colnames)):
self.grid.SetColLabelValue(i, colnames[i])
#populate the grid
for row in range(len(datalist)):
for col in range(len(colnames)):
try:
self.grid.SetCellValue(row,col,datalist[row][col])
except:
pass
self.grid.AutoSizeColumns(False) # size columns to data (from cvsomatic.py)
self.twiddle()
def twiddle(self): # from http://www.velocityreviews.com/forums/t330788-how-to-update-window-after-wxgrid-is-updated.html
x,y = self.GetSize()
self.SetSize((x, y+1))
self.SetSize((x,y))
def Exit(self, event):
if getattr(self, 'file',0):
self.file.close()
self.Close(True)
# class csv_view(wx.App):
# def OnInit(self):
# self.frame=MyFrame(None, -1, 'show CSV', size=(900,600))
# self.SetTopWindow(self.frame)
# return True
# app=csv_view()
# app.MainLoop()
app = wx.App(0)
Frame_02 = MyFrame(None)
Frame_02.Show()
app.MainLoop()
Thanks for your help in advance.
The biggest issue is that you have a parenting problem. When you create the grid widget, you add it to the frame, but not to a sizer. That causes the grid to be initialized to a small size and it gets stacked on top of the panel. To fix this, you need to set the parent of the grid to one of the panels, add the grid to a sizer and then call Layout on the panel. Here's the updated code for csv2.py:
import wx
import os
import sys, csv
import wx.grid
from csv1 import MyFrame3
class MyFrame(MyFrame3):
def __init__(self, parent, size = wx.Size(900,600)):
MyFrame3.__init__ (self, parent)
self.dirname = os.getcwd()
# Import/Open CSV
def ImportFunc( self, event ):
'''THIS IMPORTED CSV WILL NEVER EXPAND TO FIT INTO THE FRAME, PLEASE HELP?'''
dlg=wx.FileDialog(self, 'Choose a file', self.dirname, '','CSV files (*.csv)|*.csv|All files(*.*)|*.*',wx.OPEN)
if dlg.ShowModal() == wx.ID_OK:
self.dirname=dlg.GetDirectory()
self.filename=os.path.join(self.dirname,dlg.GetFilename())
self.file=file(self.filename, 'r')
#check for file format with sniffer
dialect = csv.Sniffer().sniff(self.file.read(1024))
self.file.seek(0)
csvfile=csv.reader(self.file,dialect)
filedata = [] #put contents of csvfile into a list
filedata.extend(csvfile)
self.file.seek(0)
#grab a sample and see if there is a header
sample=self.file.read(2048)
self.file.seek(0)
if csv.Sniffer().has_header(sample): #if there is a header
colnames=csvfile.next() # label columns from first line
datalist=[] # create a list without the header
datalist.extend(filedata[1:len(filedata)]) #append data without header
else:
row1=csvfile.next() #if there is NO header
colnames=[]
for i in range(len(row1)):
colnames.append('col_%d' % i) # label columns as col_1, col_2, etc
self.file.seek(0)
datalist=filedata #append data to datalist
self.file.close()
self.createGrid(datalist, colnames)
grid_sizer = wx.BoxSizer(wx.VERTICAL)
grid_sizer.Add(self.grid, 1, wx.EXPAND)
self.Right_Panel.SetSizer(grid_sizer)
self.Right_Panel.Layout()
#create the grid
def createGrid(self, datalist, colnames):
if getattr(self, 'grid', 0): self.grid.Destroy()
self.grid=wx.grid.Grid(self.Right_Panel, 0)
self.grid.CreateGrid(len(datalist), len(colnames)) #create grid, same size as file (rows, cols)
#fill in headings
for i in range(len(colnames)):
self.grid.SetColLabelValue(i, colnames[i])
#populate the grid
for row in range(len(datalist)):
for col in range(len(colnames)):
try:
self.grid.SetCellValue(row,col,datalist[row][col])
except:
pass
self.grid.AutoSizeColumns(False) # size columns to data (from cvsomatic.py)
self.twiddle()
def twiddle(self): # from http://www.velocityreviews.com/forums/t330788-how-to-update-window-after-wxgrid-is-updated.html
x,y = self.GetSize()
self.SetSize((x, y+1))
self.SetSize((x,y))
def Exit(self, event):
if getattr(self, 'file',0):
self.file.close()
self.Close(True)
import wx.lib.mixins.inspection
app = wx.App(0)
Frame_02 = MyFrame(None)
Frame_02.Show()
wx.lib.inspection.InspectionTool().Show()
app.MainLoop()
I also added the Widget Inspection Tool to your code to help me figure out how the panels were laid out and where to put the grid. It is very useful for figuring out problems with widget layout. You can read more about this handy tool on the wxPython wiki:
http://wiki.wxpython.org/Widget%20Inspection%20Tool