wxNotebook event only working on last bind - python

I have this program that has a panel with a notebook that have various panels. These panels have some text because is more specific, and then another panel that its only for plotting that is more general since i send the to the plotting panel the data from his parent. Ok, my problem is that having multiple real time plots at the same time make the application slow.
I'm trying to implement a way to stop and start these animations when changing trough the pages. So' i bind and wx.EVT_NOTEBOOK_PAGE_CHANGED in the panel of the mainframe to a method that handle this the stop and start of the animation. But when i try this, the only bind that execute is only the last one, the first two do not triggers them self. Also in this method I'm trying to and away of know witch is the current pages and witch is the selected pages, so the selected pages receive the event to start, and the current receive the event and stop.
I tried to bind the event in the pages so all the pages got it but with no luck, also tried by creating a method in panel that called the stop method and passed the event to the plot.
This is the plot panel
class live_panel_2(wx.Panel):
def __init__(self, parent):
super(live_panel_2, self).__init__(parent)
sns.set()
self.parent = parent
self.x_axis = []
self.x2_axis = []
self.y_axis = []
self.y2_axis = []
self.line_width = 1
self.flag = False
self.flag1 = False
self.figure = Figure(figsize=(15.5, 3))
self.canvas = FigureCanvas(self, -1, self.figure)
self.axis = self.figure.add_subplot(1, 1, 1)
self.axis2 = self.axis.twinx()
self.toolbar = NavigationToolbar(self.canvas)
self.toolbar.Realize()
#self.button = wx.Button(self, label='Stop')
self.figure.subplots_adjust(left=0.09, right=0.92, top=0.92, bottom=0.2, wspace=1)
self.axis.format_xdata = mdates.DateFormatter('%Y-%m-%d')
#self.axis.tick_params(axis='x', direction='inout', length=5, labelrotation=0)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.canvas, 0, wx.EXPAND, 5 )
sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND, 5)
#sizer.Add(self.button, 0, wx.ALL, 5)
self.SetSizerAndFit(sizer)
self.Bind(wx.EVT_CLOSE, self.stop)
self.canvas.draw()
#self.Bind(wx.EVT_BUTTON, self.stop, self.button)
#self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.page_stop, parent.parent)
def build(self, model, model_2, y, y2, delta, localization):
if self.flag1:
self.ani._stop()
self.x_axis = []
self.x2_axis = []
self.y_axis = []
self.y2_axis = []
self.delta = delta
self.ani = animation.FuncAnimation(self.figure, self.animate,
fargs=(self.x_axis, self.x2_axis, self.y_axis, self.y2_axis, model, model_2, y, y2, localization), interval=500)
self.flag1 = True
self.ani._start()
def close(self):
self.ani._stop()
def stop(self, event):
if self.parent == self.parent.parent.GetCurrentPage():
if self.flag == False and self.flag1 == True:
self.ani.event_source.stop()
self.flag = True
self.button.SetLabel('Start')
elif self.flag == True and self.flag1 == True:
self.ani.event_source.start()
self.flag = False
self.button.SetLabel('Stop')
#Animation
def animate(self, i, x_axis, x2_axis, y_axis, y2_axis, model, model2, y, y2, localization):
#Data query
self.now = datetime.now()
self.now_delta = self.now - timedelta(minutes=self.delta)
if not self.x_axis:
with session_scope() as s:
value = s.query(y).order_by(model.Datetime.desc()).filter(model.Datetime < self.now).filter(model.Datetime > self.now_delta).all()
value2 = s.query(y2).order_by(model2.Datetime.desc()).filter(model2.Datetime > self.now_delta).filter(model2.Datetime < self.now).all()
time = s.query(model.Datetime).order_by(model.Datetime.desc()).filter(model.Datetime > self.now_delta).filter(model.Datetime < self.now).all()
time2 = s.query(model2.Datetime).order_by(model2.Datetime.desc()).filter(model2.Datetime > self.now_delta).filter(model2.Datetime < self.now).all()
for i in reversed(value):
self.y_axis.append(i[0])
for i in reversed(value2):
self.y2_axis.append(i[0])
for i in reversed(time):
self.x_axis.append(i[0])
for i in reversed(time2):
self.x2_axis.append(i[0])
if self.x_axis:
with session_scope() as s:
# value = s.query(y).order_by(model.Datetime.desc()).first()
# value2 = s.query(y2).order_by(model2.Datetime.desc()).first()
# time = s.query(model.Datetime).order_by(model.Datetime.desc()).first()
# time2 = s.query(model2.Datetime).order_by(model2.Datetime.desc()).first()
value = s.query(y).filter(model.Datetime > self.x_axis[-1]).all()
value2 = s.query(y2).filter(model2.Datetime > self.x2_axis[-1]).all()
time = s.query(model.Datetime).filter(model.Datetime > self.x_axis[-1]).all()
time2 = s.query(model2.Datetime).filter(model2.Datetime > self.x2_axis[-1]).all()
# if type(time) != type(None) and type(value) != type(None):
# time = time[0]
# time2 = time2[0]
# value = round(value[0], 2)
# value2 = round(value2[0], 2)
for i in value:
self.y_axis.append(i[0])
for i in value2:
self.y2_axis.append(i[0])
for i in time:
self.x_axis.append(i[0])
for i in time2:
self.x2_axis.append(i[0])
# x_axis.append(time)
# x2_axis.append(time2)
# y_axis.append(value)
# y2_axis.append(value2)
if len(x_axis) < len(y_axis):
delta = len(y_axis) - len(x_axis)
y_axis = y_axis[:-delta]
elif len(x_axis) > len(y_axis):
delta = len(x_axis) - len(y_axis)
x_axis = x_axis[:-delta]
if len(x2_axis) < len(y2_axis):
delta = len(y2_axis) - len(x2_axis)
y_axis = y_axis[:-delta]
elif len(x2_axis) > len(y2_axis):
delta = len(x2_axis) - len(y2_axis)
x2_axis = x2_axis[:-delta]
#Capacity of points
x_axis = x_axis[-self.delta*60:]
x2_axis = x2_axis[-self.delta*60:]
y_axis = y_axis[-self.delta*60:]
y2_axis = y2_axis[-self.delta*60:]
#Clear Axis
self.axis.clear()
self.axis2.clear()
#Set axis 2 format
self.axis.set_title(model.Datetime.name + ' vs ' + y.name + ' vs ' + y2.name)
self.axis.set_xlim(min(x_axis), max(x_axis))
self.axis.set_xlabel(model.Datetime.name)
self.axis.set_ylabel(y.name)
line_1 = self.axis.plot(x_axis, y_axis, linewidth=self.line_width, label=y.name)
# self.axis.annotate(str(value), xy=(time, value), xytext=(10, -2), textcoords='offset pixels',
# bbox=dict(boxstyle=custom_box_style, alpha=0.2))
#Set Axis 2 Format
self.axis2.set_xlim(min(x2_axis), max(x2_axis))
self.axis2.set_xlabel(model.Datetime.name)
self.axis2.set_ylabel(y2.name)
line_2 = self.axis2.plot(x2_axis, y2_axis, linewidth=self.line_width, color='G', label=y2.name)
# self.axis2.annotate(str(value2), xy=(time, value2), xytext=(10, -2), textcoords='offset pixels',
# bbox=dict(boxstyle=custom_box_style, alpha=0.2))
#Get lines and labels for legends
lines = line_1 + line_2
labels = [l.get_label() for l in lines]
#Turn of scientific notation
self.axis.yaxis.set_major_formatter(mticker.ScalarFormatter())
self.axis.yaxis.get_major_formatter().set_scientific(False)
self.axis.yaxis.get_major_formatter().set_useOffset(False)
self.axis2.yaxis.set_major_formatter(mticker.ScalarFormatter())
self.axis2.yaxis.get_major_formatter().set_scientific(False)
self.axis2.yaxis.get_major_formatter().set_useOffset(False)
#Set legend and turn axes 2 grid off
self.axis2.legend(lines, labels, loc=localization)
self.axis2.grid(False)
# Format plot
self.figure.canvas.mpl_connect('close_event', self.close)
#tm.sleep(1)
and this is the instrument panels.
class ccn(scrolled.ScrolledPanel):
def __init__(self, parent, title):
super(ccn, self).__init__(parent, name=title)
self.parent = parent
self.visa = visa_instruments()
self.SetupScrolling()
locations = ['Best', 'Upper left', 'Upper right', 'Lower left', 'Lower right', 'Center', 'Upper center',
'Lower center', 'Center left', 'Center right']
EVT_RESULT(self, self.update_display)
mainsizer = wx.BoxSizer(wx.VERTICAL)
current_ss_sizer = wx.BoxSizer(wx.HORIZONTAL)
stage_sizer = wx.BoxSizer(wx.HORIZONTAL)
concentration_sizer = wx.BoxSizer(wx.HORIZONTAL)
data_header = wx.StaticBoxSizer(wx.VERTICAL, self, label='Data:')
plot_border = wx.StaticBoxSizer(wx.VERTICAL, self, label='Live Plot')
plot_selector_sizer = wx.BoxSizer(wx.HORIZONTAL)
delta_sizer = wx.BoxSizer(wx.HORIZONTAL)
cmd_sizer = wx.BoxSizer(wx.HORIZONTAL)
gmd_sizer = wx.BoxSizer(wx.HORIZONTAL)
variable_1 = wx.StaticText(self, label='Variable 1: ')
variable_2 = wx.StaticText(self, label='Variable 2: ')
time_scale = wx.StaticText(self, label='Time Scale(min): ')
leyend_location_text = wx.StaticText(self, label='Leyend Location: ')
current_ss_text = wx.StaticText(self, label='Current SS:')
first_stage_text = wx.StaticText(self, label='First Stage Mon(V):')
concentration_text = wx.StaticText(self, label='CCN Number Concentration(#/m^3):')
delta_text = wx.StaticText(self, label='Delta T(C): ')
cmd_text = wx.StaticText(self, label='CMD: ')
gmd_text = wx.StaticText(self, label='GMD: ')
self.current_ss_value = wx.StaticText(self, label='N/A')
self.stage_value = wx.StaticText(self, label='N/A')
self.concentration_value = wx.StaticText(self, label='N/A')
self.delta_value = wx.StaticText(self, label='N/A')
self.cmd_value = wx.StaticText(self, label='N/A')
self.gmd_values = wx.StaticText(self, label='N/A')
self.plot = live_panel_2(self)
self.x_data_selector = wx.ComboBox(self, value='X-Axis Data')
self.y_data_selector = wx.ComboBox(self, value='Y-Axis Data')
self.time_scale = wx.ComboBox(self, value='Time Scale', size=(80, -1))
self.button = wx.Button(self, label='Enter')
self.leyend_location_selector = wx.ComboBox(self)
self.leyend_location_selector.Append(locations)
time_range = range(60)
for i in time_range:
self.time_scale.Append(str(i+1), i+1)
current_ss_sizer.Add(current_ss_text, 0, wx.ALL, 5)
current_ss_sizer.Add(self.current_ss_value, 0, wx.ALL|wx.ALIGN_RIGHT, 5)
concentration_sizer.Add(concentration_text, 0, wx.ALL, 5)
concentration_sizer.Add(self.concentration_value, 0, wx.ALL|wx.ALIGN_RIGHT, 5)
stage_sizer.Add(first_stage_text, 0, wx.ALL, 5)
stage_sizer.Add(self.stage_value, 0, wx.ALL|wx.ALIGN_RIGHT, 5)
delta_sizer.Add(delta_text, 0, wx.ALL, 5)
delta_sizer.Add(self.delta_value, 0, wx.ALL|wx.ALIGN_RIGHT, 5)
cmd_sizer.Add(cmd_text, 0, wx.ALL, 5)
cmd_sizer.Add(self.cmd_value, 0, wx.ALL|wx.ALIGN_RIGHT, 5)
gmd_sizer.Add(gmd_text, 0, wx.ALL, 5)
gmd_sizer.Add(self.gmd_values, 0, wx.ALL|wx.ALIGN_RIGHT, 5)
data_header.Add(current_ss_sizer, 0, wx.ALL, 5)
data_header.Add(stage_sizer, 0, wx.ALL, 5)
data_header.Add(concentration_sizer, 0, wx.ALL, 5)
data_header.Add(delta_sizer, 0, wx.ALL, 5)
data_header.Add(cmd_sizer, 0, wx.ALL, 5)
data_header.Add(gmd_sizer, 0, wx.ALL, 5)
plot_selector_sizer.Add(variable_1, 0, wx.ALL, 5)
plot_selector_sizer.Add(self.x_data_selector, 0, wx.ALL, 5)
plot_selector_sizer.Add(variable_2, 0, wx.ALL, 5)
plot_selector_sizer.Add(self.y_data_selector, 0, wx.ALL, 5)
plot_selector_sizer.Add(time_scale, 0, wx.ALL, 5)
plot_selector_sizer.Add(self.time_scale, 0, wx.ALL, 5)
plot_selector_sizer.Add(leyend_location_text, 0, wx.ALL, 5)
plot_selector_sizer.Add(self.leyend_location_selector, 0, wx.ALL, 5)
plot_selector_sizer.Add(self.button, 0, wx.ALL | wx.ALIGN_RIGHT, 5)
plot_border.Add(plot_selector_sizer, 0, wx.ALL, 5)
plot_border.Add(self.plot, 0, wx.ALL, 5)
mainsizer.Add(data_header,0,wx.ALL|wx.EXPAND,5)
mainsizer.Add(plot_border,0,wx.ALL|wx.EXPAND,5)
#mainsizer.Add(self.logbox, 0, wx.ALL|wx.EXPAND, 5)
self.SetSizeHints(200, 10, 700, 700) # SetSizeHints(minW, minH, maxW, maxH)
self.SetSizerAndFit(mainsizer)
DataThread(self)
#logupdater(self.logbox)
self.x_selector(wx.EVT_BUTTON)
self.Bind(wx.EVT_CLOSE, self.stop)
self.Bind(wx.EVT_BUTTON, self.builder, self.button)
#self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.plot.stop, self.parent)
def stop_plot(self, event):
self.plot.stop(event)
def builder(self, event):
x_selection = self.x_data_selector.GetCurrentSelection()
y_selection = self.y_data_selector.GetCurrentSelection()
model = ccn_model
y = self.x_data_selector.GetClientObject(x_selection)
y2 = self.y_data_selector.GetClientObject(y_selection)
location = self.leyend_location_selector.GetStringSelection().lower()
delta = self.time_scale.GetStringSelection()
self.plot.build(model, model, y, y2, int(delta), location)
def x_selector(self, event):
model = ccn_model
self.x_data_selector.Clear()
columns = model_columns(model)
for i in columns:
if i[0] != 'Datetime':
self.x_data_selector.Append(i[0], i[1])
self.y_selector(model)
def y_selector(self, model):
self.y_data_selector.Clear()
columns = model_columns(model)
for i in columns:
if i[0] != 'Datetime':
self.y_data_selector.Append(i[0], i[1])
def stop(self, event):
self.Destroy()
def update_display(self, data):
if type(data) is not type(None):
if self.current_ss_value:
self.current_ss_value.SetLabel(str(data.Current_ss))
if self.stage_value:
self.stage_value.SetLabel(str(data.first_Stage_Mon))
if self.concentration_value:
self.concentration_value.SetLabel(str(data.CCN_Number_Conc))
if self.delta_value:
self.delta_value.SetLabel(str(data.Delta_T))
if self.cmd_value:
self.cmd_value.SetLabel(str(data.CMD))
if self.gmd_values:
self.gmd_values.SetLabel(str(data.GMD))
if the code of the first panel(frame) is needed just tell me.
So' i would expect that if I'm browsing trough the pages the live plot of the current pages stops and the live plot of the page that im going starts if they where already started.

I continues my research and i solved this by adding event.skip at the end of the method.
def stop(self, event):
if self.ani:
if self.flag == False and self.flag1 == True and self.parent != self.parent.parent.GetCurrentPage():
self.ani.event_source.stop()
self.flag = True
#self.button.SetLabel('Start')
elif self.flag == True and self.flag1 == True and self.parent == self.parent.parent.GetCurrentPage():
self.ani.event_source.start()
self.flag = False
#self.button.SetLabel('Stop')
event.Skip()
Also worked on the logic but if i haven't started a live plot in a panel i receive
Traceback (most recent call last):
File "C:\Users\ACAS\PycharmProjects\ACAS\Main\GUI\plotter.py", line 172, in stop
if self.ani:
AttributeError: 'live_panel_2' object has no attribute 'ani'
I want to check if the self.ani exist but the if does not do the work.

Related

Delete item in ListCtrl Python

How can I clear list ctrl in Python?
For example when I insert the 10's item the first 8 item are deleted from the listCtrl with the possibility to continue entering item in a listCtrl.
How can i do this?
Example:
I insert: 1,2,3,4,5,6,7,8,9,10 after the 10 item i see in the listCtrl only 8,9,10 and i can insert item again.
I put some code with my example.
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.ceck = {}
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.BtnConferma = wx.Button(self.Panel, 12, "Conferma", pos=(130,38))
self.list_ctrl = wx.ListCtrl(self.Panel, pos=(10,90),size=(-1,330),style=wx.LC_REPORT|wx.BORDER_SUNKEN)
self.list_ctrl.InsertColumn(0, 'Name')
self.list_ctrl.InsertColumn(1, 'Start')
self.list_ctrl.InsertColumn(2, 'Finish', width=100)
wx.Button(self.Panel, 22, "Exit", pos=wx.Point(470,400))
self.Bind(wx.EVT_BUTTON, self.close, id=22)
self.Bind(wx.EVT_BUTTON, self.add_line, self.BtnConferma, id=12)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.list_ctrl, 0, wx.ALL|wx.EXPAND, 5)
sizer.Add(self.BtnConferma, 0, wx.ALL|wx.CENTER, 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.ceck:
self.list_ctrl.SetItemTextColour(self.ceck.get(self.ts), wx.WHITE)
self.list_ctrl.SetItemBackgroundColour(self.ceck.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:
if self.list_ctrl.GetItemCount() == 10:
for i in range(7):
self.list_ctrl.DeleteItem(1)
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")
if plus2 in self.ceck:
msg = wx.MessageDialog(self, "Duplicate 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.ceck[plus2] = self.index -1
def close(self,event):
hDialog=wx.MessageDialog(self, "°°°", "Exit", wx.OK|wx.CANCEL| wx.ICON_EXCLAMATION)
rispostaDialog=hDialog.ShowModal()
hDialog.Destroy()
if rispostaDialog == wx.ID_OK:
self.Destroy()
app = wx.App()
frame = CWindow(None, -1, "Example")
frame.Show()
frame.Center()
app.MainLoop()
You appear to have gone back (from your original post) to having the listctrl items in entry order rather than reverse entry order. That means that once again you have to remove index 0 and not index 1.
You are also not allowing for the fact that the dictionary values are now invalid if you just deleted 7 of the entries. They have to be removed if the item has been deleted and reset to the new index value if they have been left in place.
Try this, see if it gets you any closer to what you are trying to achieve:
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.ceck = {}
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.BtnConferma = wx.Button(self.Panel, 12, "Conferma", pos=(130,38))
self.list_ctrl = wx.ListCtrl(self.Panel, pos=(10,90),size=(-1,330),style=wx.LC_REPORT|wx.BORDER_SUNKEN)
self.list_ctrl.InsertColumn(0, 'Name')
self.list_ctrl.InsertColumn(1, 'Start')
self.list_ctrl.InsertColumn(2, 'Finish', width=100)
wx.Button(self.Panel, 22, "Exit", pos=wx.Point(470,400))
self.Bind(wx.EVT_BUTTON, self.close, id=22)
self.Bind(wx.EVT_BUTTON, self.add_line, self.BtnConferma, id=12)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.list_ctrl, 0, wx.ALL|wx.EXPAND, 5)
sizer.Add(self.BtnConferma, 0, wx.ALL|wx.CENTER, 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.ceck:
self.list_ctrl.SetItemTextColour(self.ceck.get(self.ts), wx.WHITE)
self.list_ctrl.SetItemBackgroundColour(self.ceck.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:
if self.list_ctrl.GetItemCount() == 10:
for i in range(7):
d = self.list_ctrl.GetItem(0,2)
del_text = d.GetText()
#remove the dictionary values for the items being deleted
try: # It may already have been popped from the dict if the colour was changed
self.ceck.pop(del_text)
except:
pass
self.list_ctrl.DeleteItem(0)
self.index -= 1
#reset the dictionary vales for the existing ctrl items they have new index values
new_idx = 0
for i in range (3):
item = self.list_ctrl.GetItemText(i,2)
self.ceck[item] = new_idx
new_idx += 1
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")
if plus2 in self.ceck:
msg = wx.MessageDialog(self, "Duplicate 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.ceck[plus2] = self.index -1
def close(self,event):
hDialog=wx.MessageDialog(self, "°°°", "Exit", wx.OK|wx.CANCEL| wx.ICON_EXCLAMATION)
rispostaDialog=hDialog.ShowModal()
hDialog.Destroy()
if rispostaDialog == wx.ID_OK:
self.Destroy()
app = wx.App()
frame = CWindow(None, -1, "Example")
frame.Show()
frame.Center()
app.MainLoop()

pass information among panels in wxpython

I have a pretty complicated wxpython app that has nested notebooks and panels. Basically the structure is that in my main frame I have a notebook (let's say notebook 1, in one page of the notebook I have two panels (upper and lower). In the lower panel I have another notebook (lets say notebook 2). So the question is how do I pass information between these two notebooks pages, and to the upper panels.
I know that there are basically three ways of passing information: by event id, by publisher, by .parent and .child. However I am really confused with the difference of these three methods and when to use them.
I have attached my code as below.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import datetime, time
import wx, sys, wx.grid
import xlrd
import pandas as pd
import numpy as np
import wx.lib.scrolledpanel as scrolled
EVEN_ROW_COLOUR = '#CCE6FF'
GRID_LINE_COLOUR = '#ccc'
import pandas as pd
import numpy as np
class ResultTable(wx.grid.PyGridTableBase):
def __init__(self, data=None):
wx.grid.PyGridTableBase.__init__(self)
self.data = data
self.odd=wx.grid.GridCellAttr()
self.odd.SetBackgroundColour("sky blue")
self.odd.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
self.even=wx.grid.GridCellAttr()
self.even.SetBackgroundColour("sea green")
self.even.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
def GetNumberRows(self):
return self.data.shape[0]
def GetNumberCols(self):
return self.data.shape[1]
def GetValue(self, row, col):
return self.data.loc[row][col]
def GetColLabelValue(self, row):
return list(self.data)[row]
def SetValue(self, row, col, value):
pass
def GetAttr(self, row, col, prop):
attr = wx.grid.GridCellAttr()
if row % 2 == 1:
attr.SetBackgroundColour(EVEN_ROW_COLOUR)
return attr
class ResultTablePanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
grid = wx.grid.Grid(self)
result = pd.DataFrame({'a' : np.random.randn(100), 'b' : np.random.randn(100), 'c' : np.random.randn(100)})
table = ResultTable(result)
grid.SetTable(table)
grid.AutoSize()
grid.AutoSizeColumns(True)
grid.SetGridLineColour(GRID_LINE_COLOUR)
grid.EnableDragGridSize( False )
grid.SetRowLabelSize( 50 )
grid.SetDefaultCellAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(grid, 1, wx.ALL|wx.EXPAND)
self.SetSizer(sizer)
btn_ID = parent.GetParent().GetParent().topPanel.analysisButton.GetId()
self.Bind(wx.EVT_BUTTON, self.getResult, id = btn_ID)
def getResult(self,e):
"""
This function should get the variables passed by the analysisOrder function,
once the button on the SearchConditionPanel is clicked.
"""
fileName, start_date, end_date = parent.GetParent().GetParent().topPanel.analysisOrder
print "result get as follows:"
print fileName, start_date, end_date
class SearchConditionPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
# Creat input box for searching time period
nameTitleLable = wx.StaticText(self,-1, label=u"File Name:")
self.fileNameInput = wx.TextCtrl(self,-1, "20170310221612")
dateTitleLable = wx.StaticText(self,-1, label=u"Date range:")
yearLable1 = wx.StaticText(self, label=u"Year:")
monthLable1 = wx.StaticText(self,-1, label=u"Month:")
dayLable1 = wx.StaticText(self,-1, label=u"Day:")
yearLable2 = wx.StaticText(self,-1, label=u"Year:")
monthLable2 = wx.StaticText(self,-1, label=u"Month:")
dayLable2 = wx.StaticText(self,-1, label=u"Day:")
startLable = wx.StaticText(self,-1, label=u"Start Date:")
endLable = wx.StaticText(self,-1, label=u"End Date:")
self.startYearInput = wx.TextCtrl(self,1, "2016")
self.startMonthInput = wx.TextCtrl(self,-1, "10")
self.startDayInput = wx.TextCtrl(self,-1, "30")
self.endYearInput = wx.TextCtrl(self,-1, "2017")
self.endMonthInput = wx.TextCtrl(self,-1, "11")
self.endDayInput = wx.TextCtrl(self,-1, "22")
self.analysisButton = wx.Button(self, -1, label = u'Start')
exportButton = wx.Button(self, -1, label = u'Export')
exportButton.Disable()
## Set up overall layout for the panel
hbox = wx.BoxSizer(wx.HORIZONTAL)
vbox_File_button = wx.BoxSizer(wx.VERTICAL)
hbox_file = wx.BoxSizer(wx.HORIZONTAL)
vbox_date = wx.BoxSizer(wx.VERTICAL)
hbox_button = wx.BoxSizer(wx.HORIZONTAL)
hbox_startDate = wx.BoxSizer(wx.HORIZONTAL)
hbox_endDate = wx.BoxSizer(wx.HORIZONTAL)
hbox.Add(vbox_date, 0, wx.ALIGN_LEFT | wx.ALL, 5)
hbox.Add(wx.StaticLine(self, style=wx.LI_VERTICAL), 0, wx.ALL | wx.EXPAND, 5)
hbox.Add(vbox_File_button, 0, wx.ALIGN_LEFT | wx.ALL, 5)
## Setup the layout for the right side
vbox_File_button.Add(hbox_file, 0, wx.ALIGN_LEFT | wx.ALL, 5)
vbox_File_button.Add(wx.StaticLine(self), 0, wx.ALL | wx.EXPAND, 5)
vbox_File_button.Add(hbox_button, 0, wx.ALIGN_LEFT | wx.ALL, 5)
hbox_file.Add(nameTitleLable, 0, wx.TOP | wx.LEFT | wx.BOTTOM, 10)
hbox_file.Add(self.fileNameInput, 0, wx.ALL | wx.EXPAND, 5)
hbox_button.Add(self.analysisButton, 1, wx.TOP | wx.LEFT, 10)
hbox_button.Add(exportButton, 1, wx.TOP | wx.LEFT, 10)
## Setup the layout for the left side
vbox_date.Add(dateTitleLable, 0, wx.ALL, 5)
vbox_date.Add(hbox_startDate, 0, wx.ALL | wx.EXPAND, 5)
vbox_date.Add(hbox_endDate, 0, wx.ALL | wx.EXPAND, 5)
hbox_startDate.Add(startLable, 0, wx.ALL, 5)
hbox_startDate.Add(yearLable1, 0, wx.TOP | wx.LEFT | wx.BOTTOM, 5)
hbox_startDate.Add(self.startYearInput, 0, wx.ALL, 5)
hbox_startDate.Add(monthLable1, 0, wx.TOP | wx.LEFT | wx.BOTTOM, 5)
hbox_startDate.Add(self.startMonthInput, 0, wx.ALL|wx.EXPAND, 5)
hbox_startDate.Add(dayLable1, 0, wx.TOP | wx.LEFT | wx.BOTTOM, 5)
hbox_startDate.Add(self.startDayInput, 0, wx.ALL|wx.EXPAND, 5)
hbox_endDate.Add(endLable, 0, wx.LEFT | wx.RIGHT, 5)
hbox_endDate.Add(yearLable2, 0, wx.LEFT, 5)
hbox_endDate.Add(self.endYearInput, 0, wx.LEFT | wx.RIGHT, 5)
hbox_endDate.Add(monthLable2, 0, wx.LEFT, 5)
hbox_endDate.Add(self.endMonthInput, 0, wx.LEFT | wx.RIGHT, 5)
hbox_endDate.Add(dayLable2, 0, wx.LEFT, 5)
hbox_endDate.Add(self.endDayInput, 0, wx.LEFT, 5)
self.SetSizer(hbox)
self.Bind(wx.EVT_BUTTON, self.analysisOrder, id=self.analysisButton.GetId())
def analysisOrder(self,e):
fileName_temp = self.fileNameInput.GetValue().strip()
fileName = fileName_temp + '.xls'
start_date = self.startYearInput.GetValue().strip() + '-' + self.startMonthInput.GetValue().strip() + '-' + self.startDayInput.GetValue().strip()
end_date = self.endYearInput.GetValue().strip() + '-' + self.endMonthInput.GetValue().strip() + '-' + self.endDayInput.GetValue().strip()
print "analysis order button called"
return fileName, start_date, end_date
class ResultNotebook(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# Creat notebooks for window layout
result_notebook = wx.Notebook(self)
data_page = ResultTablePanel(result_notebook, -1)
result_notebook.AddPage(data_page, u"Display Data")
# Set up a boxsizer for the tabs
result_notebook_sizer = wx.BoxSizer(wx.HORIZONTAL)
result_notebook_sizer.Add(result_notebook, 1, wx.EXPAND)
self.SetSizer(result_notebook_sizer)
class ModePage(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# Localize all the panels
self.topPanel = SearchConditionPanel(self, -1)
self.botPanel = ResultNotebook(self)
#Set up the panels, align and position them in the right place
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.topPanel, 0, wx.EXPAND | wx.ALL, 5)
vbox.Add(self.botPanel, -1, wx.EXPAND | wx.ALL, 5)
self.SetSizer(vbox)
self.Centre()
self.Show(True)
class FreqPage(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# t = wx.StaticText(self, -1, "This is a Frequency Page object", (20,20))
# Localize all the panels
topPanel = SearchConditionPanel(self, -1)
t = wx.StaticText(self, -1, "This is a Frequency Page object")
#Set up the panels, align and position them in the right place
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(topPanel, 0, wx.EXPAND | wx.ALL, 5)
vbox.Add(t, -1, wx.EXPAND | wx.ALL, 5)
self.SetSizer(vbox)
self.Centre()
self.Show(True)
class OrderPage(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# Localize all the panels
self.topPanel = SearchConditionPanel(self, -1)
self.botPanel = ResultNotebook(self)
#Set up the panels, align and position them in the right place
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.topPanel, 0, wx.EXPAND | wx.ALL, 5)
vbox.Add(self.botPanel, -1, wx.EXPAND | wx.ALL, 5)
self.SetSizer(vbox)
self.Centre()
self.Show(True)
class ShopPage(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# Creat notebooks for window layout
shop_notebook = wx.Notebook(self)
mode_page = ModePage(shop_notebook)
freq_page = FreqPage(shop_notebook)
shop_notebook.AddPage(mode_page, u"Mode Analysis")
shop_notebook.AddPage(freq_page, u"Frequency Analysis")
# Set up a boxsizer for the tabs
shop_page_sizer = wx.BoxSizer(wx.HORIZONTAL)
shop_page_sizer.Add(shop_notebook, 1, wx.EXPAND)
self.SetSizer(shop_page_sizer)
##**----------------------------------------------------------------------------------**##
##**-------------- Create a windows to display the entire system ---------------------**##
class OrderAnalysis(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(1024, 576))
# self.Maximize(True) # Default display to be maximized
panel = wx.Panel(self, -1)
# Creat notebooks for window layout
main_notebook = wx.Notebook(panel, style=wx.NB_LEFT)
main_notebook.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT,
wx.FONTWEIGHT_NORMAL,
wx.FONTSTYLE_NORMAL))
# create the page windows as children of the notebook
order_page = OrderPage(main_notebook)
shop_page = ShopPage(main_notebook)
# add the pages to the notebook with the label to show on the tab
main_notebook.AddPage(order_page, u"Order Analysis")
main_notebook.AddPage(shop_page, u"Shop Analysis")
# finally, put the notebook in a sizer for the panel to manage
# the layout
sizer = wx.BoxSizer()
sizer.Add(main_notebook, 1, wx.EXPAND)
panel.SetSizer(sizer)
self.Centre()
self.Show(True)
if __name__ == "__main__":
app = wx.App()
OrderAnalysis(None, -1, 'Order Info Analyser')
app.MainLoop()
As you can see, I have a search condition panel and a result panel that are used in different pages. For each specific page, the search condition and result could be different and only for that page. So my question is, what is the best way to pass the search condition (i.e. data and file name) to the corresponding page to display the result (i.e. the "getResult" function inside "ResultTablePanel" doesn't work).
For example, inside the "order page", the search condition panel has user input start and end dates, and the file name. Below the search condition panel is the result panel showing the computed result based on the search condition. Once the "Start" button is clicked, the "start date", "end date" and "file name" variables are passed to the result panel ("ResultTablePanel") within the "order page". Similarly, since the "Mode page" also calls both "ResultTablePanel" and "SearchConditionPanel", it should have its own "start date", "end date" and "file name" variables (note that they can be same or different from the ones inside "order page"), and its own result displayed in "ResultTablePanel".
Thank you in advance for taking time reviewing and answering my question.
================================================================================
Thank you guys for the help, I have figured it out using PubSub and .parent methods combined. I have attached my solution code as follows:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import datetime, time
import wx, sys, wx.grid
import xlrd
import pandas as pd
import numpy as np
import wx.lib.scrolledpanel as scrolled
EVEN_ROW_COLOUR = '#CCE6FF'
GRID_LINE_COLOUR = '#ccc'
import pandas as pd
import numpy as np
from wx.lib.pubsub import pub
class ResultTable(wx.grid.PyGridTableBase):
def __init__(self, data=None):
wx.grid.PyGridTableBase.__init__(self)
self.data = data
self.odd=wx.grid.GridCellAttr()
self.odd.SetBackgroundColour("sky blue")
self.odd.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
self.even=wx.grid.GridCellAttr()
self.even.SetBackgroundColour("sea green")
self.even.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
def GetNumberRows(self):
if self.data.empty:
return 5
else:
return self.data.shape[0]
def GetNumberCols(self):
if self.data.empty:
return 5
else:
return self.data.shape[1]
def GetValue(self, row, col):
if self.data.empty:
return None
else:
return self.data.loc[row][col]
def GetColLabelValue(self, row):
if self.data.empty:
return None
else:
return list(self.data)[row]
def SetValue(self, row, col, value):
pass
def GetAttr(self, row, col, prop):
attr = wx.grid.GridCellAttr()
if row % 2 == 1:
attr.SetBackgroundColour(EVEN_ROW_COLOUR)
return attr
def ResetView(self):
"""Trim/extend the control's rows and update all values"""
self.getGrid().BeginBatch()
for current, new, delmsg, addmsg in [
(self.currentRows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED),
(self.currentColumns, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED),
]:
if new < current:
msg = wx.grid.GridTableMessage(
self,
delmsg,
new, # position
current-new,
)
self.getGrid().ProcessTableMessage(msg)
elif new > current:
msg = wx.grid.GridTableMessage(
self,
addmsg,
new-current
)
self.getGrid().ProcessTableMessage(msg)
self.UpdateValues()
self.getGrid().EndBatch()
# The scroll bars aren't resized (at least on windows)
# Jiggling the size of the window rescales the scrollbars
h,w = grid.GetSize()
grid.SetSize((h+1, w))
grid.SetSize((h, w))
grid.ForceRefresh()
def UpdateValues( self ):
"""Update all displayed values"""
msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
self.getGrid().ProcessTableMessage(msg)
class ResultTablePanel(wx.Panel):
def __init__(self, parent, id, page):
wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
self.grid = wx.grid.Grid(self)
self.parent = parent
result = pd.DataFrame({'0' : np.random.randn(100), 'b' : np.random.randn(100), 'c' : np.random.randn(100)})
result = pd.DataFrame()
table = ResultTable(result)
self.grid.SetTable(table)
self.grid.AutoSize()
self.grid.AutoSizeColumns(True)
self.grid.SetGridLineColour(GRID_LINE_COLOUR)
self.grid.EnableDragGridSize( False )
self.grid.SetRowLabelSize( 50 )
self.grid.SetDefaultCellAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.grid, 1, wx.ALL|wx.EXPAND)
self.SetSizer(sizer)
pub.subscribe(self.getResult, "panelListener")
def getResult(self, message, page):
"""
This function should get the variables passed by the analysisOrder function,
once the button on the SearchConditionPanel is clicked.
"""
result = pd.DataFrame()
if page == "Order" and self.parent.GetParent().GetParent().page_identifier == "Order":
# For test purpose only
result = pd.DataFrame({'0' : np.random.randn(100), 'b' : np.random.randn(100), 'c' : np.random.randn(100)}) ## For test only
print "Update Order page"
table = ResultTable(result)
self.grid.SetTable(table)
self.Refresh()
if page == "Mode" and self.parent.GetParent().GetParent().page_identifier == "Mode":
result = pd.DataFrame({'0' : np.random.randn(1000), 'b' : np.random.randn(1000)}) ## For test only
print "Update Mode page"
table = ResultTable(result)
self.grid.SetTable(table)
self.Refresh()
else:
pass
class SearchConditionPanel(wx.Panel):
def __init__(self, parent, id, pageID):
wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
# Creat input box for searching time period
nameTitleLable = wx.StaticText(self,-1, label=u"File Name:")
self.fileNameInput = wx.TextCtrl(self,-1, "20170310221612")
dateTitleLable = wx.StaticText(self,-1, label=u"Date range:")
yearLable1 = wx.StaticText(self, label=u"Year:")
monthLable1 = wx.StaticText(self,-1, label=u"Month:")
dayLable1 = wx.StaticText(self,-1, label=u"Day:")
yearLable2 = wx.StaticText(self,-1, label=u"Year:")
monthLable2 = wx.StaticText(self,-1, label=u"Month:")
dayLable2 = wx.StaticText(self,-1, label=u"Day:")
startLable = wx.StaticText(self,-1, label=u"Start Date:")
endLable = wx.StaticText(self,-1, label=u"End Date:")
self.startYearInput = wx.TextCtrl(self,1, "2016")
self.startMonthInput = wx.TextCtrl(self,-1, "10")
self.startDayInput = wx.TextCtrl(self,-1, "30")
self.endYearInput = wx.TextCtrl(self,-1, "2017")
self.endMonthInput = wx.TextCtrl(self,-1, "11")
self.endDayInput = wx.TextCtrl(self,-1, "22")
self.analysisButton = wx.Button(self, -1, label = u'Start')
exportButton = wx.Button(self, -1, label = u'Export')
exportButton.Disable()
## Set up overall layout for the panel
hbox = wx.BoxSizer(wx.HORIZONTAL)
vbox_File_button = wx.BoxSizer(wx.VERTICAL)
hbox_file = wx.BoxSizer(wx.HORIZONTAL)
vbox_date = wx.BoxSizer(wx.VERTICAL)
hbox_button = wx.BoxSizer(wx.HORIZONTAL)
hbox_startDate = wx.BoxSizer(wx.HORIZONTAL)
hbox_endDate = wx.BoxSizer(wx.HORIZONTAL)
hbox.Add(vbox_date, 0, wx.ALIGN_LEFT | wx.ALL, 5)
hbox.Add(wx.StaticLine(self, style=wx.LI_VERTICAL), 0, wx.ALL | wx.EXPAND, 5)
hbox.Add(vbox_File_button, 0, wx.ALIGN_LEFT | wx.ALL, 5)
## Setup the layout for the right side
vbox_File_button.Add(hbox_file, 0, wx.ALIGN_LEFT | wx.ALL, 5)
vbox_File_button.Add(wx.StaticLine(self), 0, wx.ALL | wx.EXPAND, 5)
vbox_File_button.Add(hbox_button, 0, wx.ALIGN_LEFT | wx.ALL, 5)
hbox_file.Add(nameTitleLable, 0, wx.TOP | wx.LEFT | wx.BOTTOM, 10)
hbox_file.Add(self.fileNameInput, 0, wx.ALL | wx.EXPAND, 5)
hbox_button.Add(self.analysisButton, 1, wx.TOP | wx.LEFT, 10)
hbox_button.Add(exportButton, 1, wx.TOP | wx.LEFT, 10)
## Setup the layout for the left side
vbox_date.Add(dateTitleLable, 0, wx.ALL, 5)
vbox_date.Add(hbox_startDate, 0, wx.ALL | wx.EXPAND, 5)
vbox_date.Add(hbox_endDate, 0, wx.ALL | wx.EXPAND, 5)
hbox_startDate.Add(startLable, 0, wx.ALL, 5)
hbox_startDate.Add(yearLable1, 0, wx.TOP | wx.LEFT | wx.BOTTOM, 5)
hbox_startDate.Add(self.startYearInput, 0, wx.ALL, 5)
hbox_startDate.Add(monthLable1, 0, wx.TOP | wx.LEFT | wx.BOTTOM, 5)
hbox_startDate.Add(self.startMonthInput, 0, wx.ALL|wx.EXPAND, 5)
hbox_startDate.Add(dayLable1, 0, wx.TOP | wx.LEFT | wx.BOTTOM, 5)
hbox_startDate.Add(self.startDayInput, 0, wx.ALL|wx.EXPAND, 5)
hbox_endDate.Add(endLable, 0, wx.LEFT | wx.RIGHT, 5)
hbox_endDate.Add(yearLable2, 0, wx.LEFT, 5)
hbox_endDate.Add(self.endYearInput, 0, wx.LEFT | wx.RIGHT, 5)
hbox_endDate.Add(monthLable2, 0, wx.LEFT, 5)
hbox_endDate.Add(self.endMonthInput, 0, wx.LEFT | wx.RIGHT, 5)
hbox_endDate.Add(dayLable2, 0, wx.LEFT, 5)
hbox_endDate.Add(self.endDayInput, 0, wx.LEFT, 5)
self.SetSizer(hbox)
self.Bind(wx.EVT_BUTTON, self.analysisOrder, id=self.analysisButton.GetId())
self.page_ID = pageID
def analysisOrder(self,e):
fileName_temp = self.fileNameInput.GetValue().strip()
fileName = fileName_temp + '.xls'
start_date = self.startYearInput.GetValue().strip() + '-' + self.startMonthInput.GetValue().strip() + '-' + self.startDayInput.GetValue().strip()
end_date = self.endYearInput.GetValue().strip() + '-' + self.endMonthInput.GetValue().strip() + '-' + self.endDayInput.GetValue().strip()
print "analysis order button called"
pub.sendMessage("panelListener", message=fileName, page = self.page_ID)
return fileName, start_date, end_date
class ResultNotebook(wx.Panel):
def __init__(self, parent, pageID):
wx.Panel.__init__(self, parent)
# Creat notebooks for window layout
result_notebook = wx.Notebook(self)
self.data_page = ResultTablePanel(result_notebook, -1, page = pageID)
result_notebook.AddPage(self.data_page, u"Display Data")
# Set up a boxsizer for the tabs
result_notebook_sizer = wx.BoxSizer(wx.HORIZONTAL)
result_notebook_sizer.Add(result_notebook, 1, wx.EXPAND)
self.SetSizer(result_notebook_sizer)
class ModePage(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.page_identifier = "Mode"
# Localize all the panels
self.topPanel = SearchConditionPanel(self, -1, pageID = "Mode")
self.botPanel = ResultNotebook(self, pageID = "Mode")
#Set up the panels, align and position them in the right place
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.topPanel, 0, wx.EXPAND | wx.ALL, 5)
vbox.Add(self.botPanel, -1, wx.EXPAND | wx.ALL, 5)
self.SetSizer(vbox)
self.Centre()
self.Show(True)
class FreqPage(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# t = wx.StaticText(self, -1, "This is a Frequency Page object", (20,20))
# Localize all the panels
topPanel = SearchConditionPanel(self, -1, pageID = "Frequency")
t = wx.StaticText(self, -1, "This is a Frequency Page object")
#Set up the panels, align and position them in the right place
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(topPanel, 0, wx.EXPAND | wx.ALL, 5)
vbox.Add(t, -1, wx.EXPAND | wx.ALL, 5)
self.SetSizer(vbox)
self.Centre()
self.Show(True)
class OrderPage(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.page_identifier = "Order"
# Localize all the panels
self.topPanel = SearchConditionPanel(self, -1, pageID = "Order")
self.botPanel = ResultNotebook(self, pageID = "Order")
#Set up the panels, align and position them in the right place
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.topPanel, 0, wx.EXPAND | wx.ALL, 5)
vbox.Add(self.botPanel, -1, wx.EXPAND | wx.ALL, 5)
self.SetSizer(vbox)
self.Centre()
self.Show(True)
class ShopPage(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# Creat notebooks for window layout
shop_notebook = wx.Notebook(self)
mode_page = ModePage(shop_notebook)
freq_page = FreqPage(shop_notebook)
shop_notebook.AddPage(mode_page, u"Mode Analysis")
shop_notebook.AddPage(freq_page, u"Frequency Analysis")
# Set up a boxsizer for the tabs
shop_page_sizer = wx.BoxSizer(wx.HORIZONTAL)
shop_page_sizer.Add(shop_notebook, 1, wx.EXPAND)
self.SetSizer(shop_page_sizer)
##**----------------------------------------------------------------------------------**##
##**-------------- Create a windows to display the entire system ---------------------**##
class OrderAnalysis(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(1024, 576))
# self.Maximize(True) # Default display to be maximized
panel = wx.Panel(self, -1)
# Creat notebooks for window layout
main_notebook = wx.Notebook(panel, style=wx.NB_LEFT)
main_notebook.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT,
wx.FONTWEIGHT_NORMAL,
wx.FONTSTYLE_NORMAL))
# create the page windows as children of the notebook
order_page = OrderPage(main_notebook)
shop_page = ShopPage(main_notebook)
# add the pages to the notebook with the label to show on the tab
main_notebook.AddPage(order_page, u"Order Analysis")
main_notebook.AddPage(shop_page, u"Shop Analysis")
# finally, put the notebook in a sizer for the panel to manage
# the layout
sizer = wx.BoxSizer()
sizer.Add(main_notebook, 1, wx.EXPAND)
panel.SetSizer(sizer)
self.Centre()
self.Show(True)
if __name__ == "__main__":
app = wx.App()
OrderAnalysis(None, -1, 'Order Info Analyser')
app.MainLoop()
Thank you everyone again! Much appreciated.
I usually recommend using Pubsub for this sort of thing. It's very easy to implement and makes it easy to pass a message to one or more recipients (panels).
Here's a simple example:
import wx
from wx.lib.pubsub import pub
class OtherFrame(wx.Frame):
""""""
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, wx.ID_ANY, "Secondary Frame")
panel = wx.Panel(self)
msg = "Enter a Message to send to the main frame"
instructions = wx.StaticText(panel, label=msg)
self.msgTxt = wx.TextCtrl(panel, value="")
closeBtn = wx.Button(panel, label="Send and Close")
closeBtn.Bind(wx.EVT_BUTTON, self.onSendAndClose)
sizer = wx.BoxSizer(wx.VERTICAL)
flags = wx.ALL|wx.CENTER
sizer.Add(instructions, 0, flags, 5)
sizer.Add(self.msgTxt, 0, flags, 5)
sizer.Add(closeBtn, 0, flags, 5)
panel.SetSizer(sizer)
def onSendAndClose(self, event):
"""
Send a message and close frame
"""
msg = self.msgTxt.GetValue()
pub.sendMessage("panelListener", message=msg)
pub.sendMessage("panelListener", message="test2", arg2="2nd argument!")
self.Close()
class MyPanel(wx.Panel):
""""""
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
pub.subscribe(self.myListener, "panelListener")
btn = wx.Button(self, label="Open Frame")
btn.Bind(wx.EVT_BUTTON, self.onOpenFrame)
def myListener(self, message, arg2=None):
"""
Listener function
"""
print "Received the following message: " + message
if arg2:
print "Received another arguments: " + str(arg2)
def onOpenFrame(self, event):
"""
Opens secondary frame
"""
frame = OtherFrame()
frame.Show()
class MyFrame(wx.Frame):
""""""
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="PubSub Tutorial")
panel = MyPanel(self)
self.Show()
if __name__ == "__main__":
app = wx.App(False)
frame = MyFrame()
app.MainLoop()
And here is some additional information:
https://wxpython.org/Phoenix/docs/html/wx.lib.pubsub.html
https://www.blog.pythonlibrary.org/2013/09/05/wxpython-2-9-and-the-newer-pubsub-api-a-simple-tutorial/
You mention three ways of passing information but I have to confess I don't understand what you are talking about (and I've written many wxWidget applications). One way of handling the situation you describe is for the event handler to call a function in the parent class, which can then relay the information to other functions/classes. Schematically:
class A:
def __init__(self):
B(self)
self.c = C(self)
def a_function(self, *data):
# do something with the data
# you can pass the information to class C here
class B:
def __init__(self, parent):
self.parent = parent
def an_event_handler(self):
data = something
self.parent.a_function(data)
# or use wx.CallAfter for later execution
class C:
pass
Another solution is the MVC concept, where your event handler passes its information to a model class which stores it or processes it further. This model class can raise a custom wx Event, which components of the UI can then handle as necessary to redraw any affected widgets.

Print out / list pending events queue from an event handler in wx python?

In the code below (Slow GUI update of a wx (Python) widget?), how could I print out a list of which events are queued at that moment, let's say from the OnAngleChanged handler?
I've seen that there exists e.g. wx.PyApp.ProcessPendingEvents(), so there must be a list of pending events of sorts; but ProcessPendingEvents() seems to be an interface to a C function (as per wx/_core.py), and I cannot really find what that list is, or how to have it printed from Python.
import wx
import wx.lib.agw.knobctrl as KC
# started from: http://wxpython.org/Phoenix/docs/html/lib.agw.knobctrl.html
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1, "KnobCtrl Demo")
self.panel = wx.Panel(self)
self.knob1 = KC.KnobCtrl(self, -1, size=(100, 100))
self.knob1.SetTags(range(0, 151, 10))
self.knob1.SetAngularRange(-45, 225)
self.knob1.SetValue(45)
# explicit sizes here - cannot figure out the expands ATM
self.text_ctrl_1 = wx.TextCtrl(self, -1, "0", size=(50, -1))
self.slider_1 = wx.Slider(self, -1, 0, -12, 12, style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS|wx.SL_INVERSE, size=(150, -1))
self.text_ctrl_2 = wx.TextCtrl(self, -1, "0", size=(50, -1))
main_sizer = wx.BoxSizer(wx.VERTICAL)
main_sizer.Add(self.knob1, 0, wx.EXPAND | wx.ALL, 20)
main_sizer.Add(self.text_ctrl_1, 0, wx.EXPAND, 20)
main_sizer.Add(self.slider_1, 0, wx.EXPAND , 20)
main_sizer.Add(self.text_ctrl_2, 0, wx.EXPAND, 20)
self.panel.SetSizer(main_sizer)
main_sizer.Layout()
self.knob1.Bind(KC.EVT_KC_ANGLE_CHANGED, self.OnAngleChanged)
self.slider_1.Bind(wx.EVT_SCROLL, self.OnSliderScroll)
def OnAngleChanged(self, e):
theknob = e.EventObject
x = theknob._mousePosition.x
y = theknob._mousePosition.y
ang = theknob.GetAngleFromCoord(x, y)
self.text_ctrl_1.SetValue("%.2f" % (ang))
self.text_ctrl_1.Refresh() # no dice
def OnSliderScroll(self, e):
obj = e.GetEventObject()
val = obj.GetValue()
self.text_ctrl_2.SetValue(str(val))
# our normal wxApp-derived class, as usual
app = wx.App(0)
frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show()
app.MainLoop()

wxpython listctrl and fix column widths

I am trying to make a "table" look good within my panel. This issue I'm having is that the table fills up the panel but everything is to the left. I would like to have each column be the same size and span the entire width of the panel. I have seen the ListCtrlAutoWidthMixin but am not sure how I could utilize this. Here is what I have in code:
self.Analysis = scrolled.ScrolledPanel(self.Notebook3, -1)
# Set Up Analysis Page (Page has four panels -- I care about Top left one)
self.AnalysisUL = wx.Panel(self.Analysis,-1, style=wx.BORDER_NONE)
self.AnalysisUR = wx.Panel(self.Analysis,-1, style=wx.BORDER_NONE)
self.AnalysisLL = wx.Panel(self.Analysis,-1, style=wx.BORDER_NONE)
self.AnalysisLR = wx.Panel(self.Analysis,-1, style=wx.BORDER_NONE)
# Top Left Box (Analyze Button and Projected Points Total)
self.Picks_Left = wx.ListCtrl(self.AnalysisUL,-1,style=wx.LC_REPORT | wx.BORDER_NONE)
self.Picks_Left.InsertColumn(1,'col1')
self.Picks_Left.InsertColumn(2,'col2',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(3,'col3',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(4,'col4',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.SetColumnWidth(0,-2)
self.Picks_Left.SetColumnWidth(1,-2)
self.Picks_Left.SetColumnWidth(2,-2)
self.Picks_Left.SetColumnWidth(3,-2)
# Sizer
vbox_UL = wx.BoxSizer(wx.VERTICAL)
#Title for Table
fontUL = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)
self.UL_text = wx.StaticText(self.AnalysisUL, -1, 'Title')
self.UL_text.SetFont(fontUL)
vbox_UL.Add(self.UL_text, 0, wx.CENTER|wx.ALL,20)
vbox_UL.Add(self.Picks_Left,1,wx.EXPAND|wx.ALL,3)
self.AnalysisUL.SetSizer(vbox_UL)
Again, the table spans the panel, but all my columns are shifted to the left. Also, I do not want to set the column size manually (unless I can grab the panel size and then divide by the number of columns I have -- since the program will be used on computers with different resolutions). I have tried this approach but cannot seem to get the correct size of the panels. The numbers I get with GetSize() and GetClientSize() are all too small.
Thanks for any help!
EDIT: Code Added:
import wx
import wx.lib.mixins.listctrl as listmix
import wx.lib.scrolledpanel as scrolled
import wx.lib.agw.pybusyinfo as PBI
class TMainForm(wx.Frame):
def __init__(self, *args, **kwds):
kwds["style"] = wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER
wx.Frame.__init__(self, *args, **kwds)
self.Splitter1 = wx.SplitterWindow(self, -1)#, style=wx.SP_NOSASH)
self.Splitter2 = wx.SplitterWindow(self.Splitter1)
self.Panel1 = wx.Panel(self.Splitter2, -1)
self.Panel2 = wx.Panel(self.Splitter2, -1)
self.Splitter2.SplitHorizontally(self.Panel1,self.Panel2)
self.Panel3 = wx.Panel(self.Splitter1, -1)
self.Splitter1.SplitVertically(self.Splitter2,self.Panel3,400)
self.Notebook = wx.Notebook(self.Panel1, -1)
self.MyTeam = scrolled.ScrolledPanel(self.Notebook, -1)
self.TeamComparison = scrolled.ScrolledPanel(self.Notebook, -1)
self.MyTeam.SetupScrolling()
self.TeamComparison.SetupScrolling()
self.Notebook3 = wx.Notebook(self.Panel3, -1)
self.Analysis = scrolled.ScrolledPanel(self.Notebook3, -1)
self.Analysis.SetupScrolling()
self.AnalysisUL = wx.Panel(self.Analysis,-1, style=wx.BORDER_NONE)
self.AnalysisUR = wx.Panel(self.Analysis,-1, style=wx.BORDER_NONE)
self.AnalysisLL = wx.Panel(self.Analysis,-1, style=wx.BORDER_NONE)
self.AnalysisLR = wx.Panel(self.Analysis,-1, style=wx.BORDER_NONE)
# Top Left Box (To Fix!)
self.Picks_Left = wx.ListCtrl(self.AnalysisUL,-1,style=wx.LC_REPORT | wx.BORDER_NONE)
self.Picks_Left.InsertColumn(1,' ')
self.Picks_Left.InsertColumn(2,' ',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(3,'H1',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(4,'H2',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(5,'H#',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(6,'H4',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(7,'H5',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(8,'H6',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(9,'H7',format=wx.LIST_FORMAT_CENTRE)
## table_width = self.Picks_Left.GetSize()[0] #GetSize returns (width, height) tuple
## print table_width
## num_col = self.Picks_Left.GetColumnCount()
## col_width = table_width/num_col
## for i in range(0, num_col):
## self.Picks_Left.SetColumnWidth(i, col_width)
self.Picks_Left.SetColumnWidth(0,-2)
self.Picks_Left.SetColumnWidth(1,-2)
self.Picks_Left.SetColumnWidth(2,-2)
self.Picks_Left.SetColumnWidth(3,-2)
self.Picks_Left.SetColumnWidth(4,-2)
self.Picks_Left.SetColumnWidth(5,-2)
self.Picks_Left.SetColumnWidth(6,-2)
self.Picks_Left.SetColumnWidth(7,-2)
self.Picks_Left.SetColumnWidth(8,-2)
# Bottom Left Box (Suggested Optimal Teams)
self.Notebook_AltTeams = wx.Notebook(self.AnalysisLL, -1)
self.Alt_Team_1 = scrolled.ScrolledPanel(self.Notebook_AltTeams, -1)
self.Alt_Team_2 = scrolled.ScrolledPanel(self.Notebook_AltTeams, -1)
self.Alt_Team_3 = scrolled.ScrolledPanel(self.Notebook_AltTeams, -1)
self.Alt_Team_4 = scrolled.ScrolledPanel(self.Notebook_AltTeams, -1)
self.Alt_Team_5 = scrolled.ScrolledPanel(self.Notebook_AltTeams, -1)
self.Alt_Team_1.SetupScrolling()
self.Alt_Team_2.SetupScrolling()
self.Alt_Team_3.SetupScrolling()
self.Alt_Team_4.SetupScrolling()
self.Alt_Team_5.SetupScrolling()
# Menu Bar
self.MainMenu = wx.MenuBar()
self.FileMenu = wx.Menu()
self.FileOpenItem = wx.MenuItem(self.FileMenu, 103, "&Open\tCtrl+O", "Open a Previous Session", wx.ITEM_NORMAL)
self.FileMenu.AppendItem(self.FileOpenItem)
self.FileReloadItem = wx.MenuItem(self.FileMenu, 104, "&Reload Defaults", "Reload Default Files", wx.ITEM_NORMAL)
self.FileMenu.AppendItem(self.FileReloadItem)
self.FileSaveItem = wx.MenuItem(self.FileMenu, 102, "&Save\tCtrl+S", "Save the data", wx.ITEM_NORMAL)
self.FileMenu.AppendItem(self.FileSaveItem)
self.FileQuitItem = wx.MenuItem(self.FileMenu, wx.ID_EXIT, "&Quit\tCtrl+Q", "Quit the program", wx.ITEM_NORMAL)
self.FileMenu.AppendItem(self.FileQuitItem)
self.MainMenu.Append(self.FileMenu, "&File")
self.SetMenuBar(self.MainMenu)
# Menu Bar end
self.StatusBar = self.CreateStatusBar(2, wx.ST_SIZEGRIP)
self.__set_properties()
self.__do_layout()
self.Bind(wx.EVT_MENU, self.OnFileQuit, self.FileQuitItem)
self.Bind(wx.EVT_MENU, self.OnFileSave, self.FileSaveItem)
self.Bind(wx.EVT_MENU, self.OnFileOpen, self.FileOpenItem)
self.Bind(wx.EVT_MENU, self.OnFileReload, self.FileReloadItem)
self.OnAnalyze()
def __set_properties(self): #Set up GUI Title and Map Window
self.SetTitle("Test")
screen_x = 95 * wx.GetDisplaySize()[0]/100
screen_y = 90 * wx.GetDisplaySize()[1]/100
self.SetSize((screen_x, screen_y))
self.SetFocus()
def __do_layout(self , call_fit = True, set_sizer = True): #Create Lay-Out of GUI
# Sizer for Panel 3 (Analysis Page)
hbox = wx.BoxSizer(wx.HORIZONTAL)
vbox1 = wx.BoxSizer(wx.VERTICAL)
vbox2 = wx.BoxSizer(wx.VERTICAL)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
vbox1.Add(self.AnalysisUL, 1, wx.EXPAND | wx.ALL, 3)
vbox1.Add(self.AnalysisLL, 1, wx.EXPAND | wx.ALL, 3)
vbox2.Add(self.AnalysisUR, 1, wx.EXPAND | wx.ALL, 3)
vbox2.Add(self.AnalysisLR, 1, wx.EXPAND | wx.ALL, 3)
# Analysis Button Panel
vbox_UL = wx.BoxSizer(wx.VERTICAL)
vbox_UL3 = wx.BoxSizer(wx.HORIZONTAL)
fontUL = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)
self.UL_text = wx.StaticText(self.AnalysisUL, -1, 'Title 1')
self.UL_text.SetFont(fontUL)
Exp_Pts = ' '
fontUL = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)
self.ULText1 = wx.StaticText(self.AnalysisUL, -1, 'Title 2')
self.ULText2 = wx.StaticText(self.AnalysisUL, -1, Exp_Pts)
self.ULText1.SetFont(fontUL)
self.ULText2.SetFont(fontUL)
self.ULText2.SetForegroundColour((0,0,255))
self.ULText1.SetForegroundColour((0,0,255))
hbox2.Add(self.ULText1, 0)
hbox2.Add(self.ULText2, 0)
vbox_UL.Add(self.UL_text, 0, wx.CENTER|wx.ALL,20)
vbox_UL.Add(self.Picks_Left,1,wx.EXPAND|wx.ALL,3)
vbox_UL.Add(hbox2, 0, wx.CENTER|wx.BOTTOM,50)
self.AnalysisUL.SetSizer(vbox_UL)
# Suggested Pick Panel
vbox_LR = wx.BoxSizer(wx.HORIZONTAL)
vbox_LR2 = wx.BoxSizer(wx.VERTICAL)
font2 = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)
SuggestedSelection = ' '
self.SuggestedText1 = wx.StaticText(self.AnalysisLR, -1, ' ')
self.SuggestedText2 = wx.StaticText(self.AnalysisLR, -1, SuggestedSelection)
self.SuggestedText1.SetFont(font2)
self.SuggestedText2.SetFont(font2)
self.SuggestedText2.SetForegroundColour((0,0,255))
vbox_LR2.Add(self.SuggestedText1,0,wx.ALIGN_CENTRE)
vbox_LR2.Add(wx.StaticText(self.AnalysisLR, -1, ''),0,wx.CENTER)
vbox_LR2.Add(wx.StaticText(self.AnalysisLR, -1, ''),0,wx.CENTER)
vbox_LR2.Add(self.SuggestedText2,0,wx.ALIGN_CENTRE)
vbox_LR.Add(vbox_LR2,1,wx.CENTER)
self.AnalysisLR.SetSizer(vbox_LR)
# Projected Team Panel
sizer_LL = wx.BoxSizer(wx.VERTICAL)
self.Alt_Team_1.SetSizer(sizer_LL)
sizer_LL = wx.BoxSizer(wx.VERTICAL)
self.Alt_Team_2.SetSizer(sizer_LL)
sizer_LL = wx.BoxSizer(wx.VERTICAL)
self.Alt_Team_3.SetSizer(sizer_LL)
sizer_LL = wx.BoxSizer(wx.VERTICAL)
self.Alt_Team_4.SetSizer(sizer_LL)
sizer_LL = wx.BoxSizer(wx.VERTICAL)
self.Alt_Team_5.SetSizer(sizer_LL)
# Picks Remaining Panel
vbox_UR = wx.BoxSizer(wx.VERTICAL)
fontUR = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)
self.UR_text = wx.StaticText(self.AnalysisUR, -1, 'Title')
self.UR_text.SetFont(fontUR)
vbox_UR.Add(self.UR_text, 0, wx.CENTER)
self.AnalysisUR.SetSizer(vbox_UR)
# Finish Analysis Sizers
hbox.Add(vbox1, 1, wx.EXPAND)
hbox.Add(vbox2, 1, wx.EXPAND)
self.Analysis.SetSizer(hbox)
# Add Notebook Pages
self.Notebook.AddPage(self.MyTeam,"A")
self.Notebook.AddPage(self.TeamComparison,"B")
self.Notebook3.AddPage(self.Analysis,"CHECK ME")
self.Notebook_AltTeams.AddPage(self.Alt_Team_1,"1")
self.Notebook_AltTeams.AddPage(self.Alt_Team_2,"2")
self.Notebook_AltTeams.AddPage(self.Alt_Team_3,"3")
self.Notebook_AltTeams.AddPage(self.Alt_Team_4,"4")
self.Notebook_AltTeams.AddPage(self.Alt_Team_5,"5")
#Sizer for Panel 1
sizer_P1 = wx.BoxSizer(wx.VERTICAL)
sizer_P1.Add(self.Notebook, 1, wx.EXPAND, 0)
self.Panel1.SetSizer(sizer_P1)
#Sizer for Panel 3
sizer_P3 = wx.BoxSizer(wx.VERTICAL)
sizer_P3.Add(self.Notebook3, 1, wx.EXPAND, 0)
self.Panel3.SetSizer(sizer_P3)
#Sizer for Panel (Alt_Teams)
fontLL = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)
self.LL_text = wx.StaticText(self.AnalysisLL, -1, 'Title')
self.LL_text.SetFont(fontLL)
vbox_LL = wx.BoxSizer(wx.VERTICAL)
vbox_LL.Add(self.LL_text, 0, wx.CENTER)
#vbox_LL.Add(self.Notebook_AltTeams,1,wx.EXPAND,0)
self.AnalysisLL.SetSizer(vbox_LL)
# Split Panel Sizer
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.Splitter1,1,wx.EXPAND)
self.SetSizer(sizer)
self.Layout()
self.Centre()
# Function closes GUI
def OnFileQuit(self,event):
self.Close()
# Function reloads default parameters/lists
def OnFileReload(self,event):
self.Close()
# Function loads previously saved files
def OnFileOpen(self,event):
self.Close()
# Function saves current work
def OnFileSave(self,event):
self.Close()
# Function analyzes draft, points, adp to suggest an optimal team and the next selection
def OnAnalyze(self):
self.Picks_Left.DeleteAllItems()
self.Picks_Left.InsertStringItem(0, ' ')
self.Picks_Left.InsertStringItem(1, 'Line 1')
self.Picks_Left.InsertStringItem(2, ' ')
self.Picks_Left.InsertStringItem(3, 'Line 2')
self.Picks_Left.InsertStringItem(4, ' ')
self.Picks_Left.InsertStringItem(5, 'Line 3')
self.Picks_Left.SetStringItem(1,2, '1')
self.Picks_Left.SetStringItem(1,3, '2')
self.Picks_Left.SetStringItem(1,4, '3')
self.Picks_Left.SetStringItem(1,5, '4')
self.Picks_Left.SetStringItem(1,6, '5')
self.Picks_Left.SetStringItem(1,7, '6')
self.Picks_Left.SetStringItem(1,8, '7')
self.Picks_Left.SetStringItem(3,2, '1')
self.Picks_Left.SetStringItem(3,3, '1')
self.Picks_Left.SetStringItem(3,4, '1')
self.Picks_Left.SetStringItem(3,5, '1')
self.Picks_Left.SetStringItem(3,6, '1')
self.Picks_Left.SetStringItem(3,7, '1')
self.Picks_Left.SetStringItem(3,8, '1')
self.Picks_Left.SetStringItem(5,2, '2')
self.Picks_Left.SetStringItem(5,3, '2')
self.Picks_Left.SetStringItem(5,4, '2')
self.Picks_Left.SetStringItem(5,5, '2')
self.Picks_Left.SetStringItem(5,6, '2')
self.Picks_Left.SetStringItem(5,7, '2')
self.Picks_Left.SetStringItem(5,8, '2')
self.AnalysisUL.Layout()
app = wx.App(0)
# Code to Execute File
class TApplication(wx.App):
def OnInit(self):
wx.InitAllImageHandlers()
MainForm = TMainForm(None, -1,"")
self.SetTopWindow(MainForm)
MainForm.Show()
return 1
if __name__ == "__main__":
Application = TApplication(0)
Application.MainLoop()
I think the trouble with the GetSize() approach might have been that you were calling it before the effects of the sizer took place, so it was returning the original size of the ListCtrl before the sizer resized it to fit the panel. Try this code after the last line of your code:
table_width = self.Picks_Left.GetSize()[0] #GetSize returns (width, height) tuple
num_col = self.Picks_Left.GetColumnCount()
col_width = table_width/num_col
for i in range(0, num_col):
self.Picks_Left.SetColumnWidth(i, col_width)
You should use the RowColSizer, which is quite fit for your request. Here is a small demo how to use it:
import wx
import wx.lib.rcsizer as rcs
class TestPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, -1)
sizer = rcs.RowColSizer()
text = "This sizer lays out it's items by row and column "\
"that are specified explicitly when the item is \n"\
"added to the sizer. Grid cells with nothing in "\
"them are supported and column- or row-spanning is \n"\
"handled as well. Growable rows and columns are "\
"specified just like the wxFlexGridSizer."
sizer.Add(wx.StaticText(self, -1, text), row=1, col=1, colspan=5)
sizer.Add(wx.TextCtrl(self, -1, "(3,1)"), flag=wx.EXPAND, row=3, col=1)
sizer.Add(wx.TextCtrl(self, -1, "(3,2)"), row=3, col=2)
sizer.Add(wx.TextCtrl(self, -1, "(3,3)"), row=3, col=3)
sizer.Add(wx.TextCtrl(self, -1, "(3,4)"), row=3, col=4)
sizer.Add(
wx.TextCtrl(self, -1, "(4,2) span:(2,2)"),
flag=wx.EXPAND, row=4, col=2, rowspan=2, colspan=2
)
sizer.Add(wx.TextCtrl(self, -1, "(6,4)"), row=6, col=4)
sizer.Add(wx.TextCtrl(self, -1, "(7,2)"), row=7, col=2)
sizer.Add(wx.TextCtrl(self, -1, "(8,3)"), row=8, col=3)
sizer.Add(
wx.TextCtrl(self, -1, "(10,1) colspan: 4"),
flag=wx.EXPAND, pos=(10,1), colspan=4
)
sizer.Add(
wx.TextCtrl(self, -1, "(3,5) rowspan: 8, growable col", style=wx.TE_MULTILINE),
flag=wx.EXPAND, pos=(3,5), size=(8,1)
)
box = wx.BoxSizer(wx.VERTICAL)
box.Add(wx.Button(self, -1, "A vertical box"), flag=wx.EXPAND)
box.Add(wx.Button(self, -1, "sizer put in the"), flag=wx.EXPAND)
box.Add(wx.Button(self, -1, "RowColSizer at (12,1)"), flag=wx.EXPAND)
sizer.Add(box, pos=(12,1))
sizer.Add(
wx.TextCtrl(self, -1, "(12,2) align bottom"),
flag=wx.ALIGN_BOTTOM, pos=(12,2)
)
sizer.Add(
wx.TextCtrl(self, -1, "(12,3) align center"),
flag=wx.ALIGN_CENTER_VERTICAL, pos=(12,3)
)
sizer.Add(wx.TextCtrl(self, -1, "(12,4)"),pos=(12,4))
sizer.Add(
wx.TextCtrl(self, -1, "(12,5) full border"),
flag=wx.EXPAND|wx.ALL, border=15, pos=(12,5)
)
sizer.AddGrowableCol(5)
sizer.AddGrowableRow(9)
sizer.AddSpacer(10,10, pos=(1,6))
sizer.AddSpacer(10,10, pos=(13,1))
self.SetSizer(sizer)
self.SetAutoLayout(True)
app = wx.App()
frame = wx.Frame(None, -1)
pn = TestPanel(frame)
frame.Show()
frame.Maximize()
app.MainLoop()
The same request also could be achieved by a more fancy way use the aui
Hope it helps you out.

Python sizers - vertical column in horizontal row?

I'm learning wxPython and I'm having an issue. Here is my code below. It doesn't really work. What I'm trying to do is get a button in the top left section below the text area that says "Enter Task". I want the text input area and "enter task" button to be in a column so that the combined height of the two equals the height of the Start and Exit buttons next to them. Any help? Sizers confuse me.
import wx
import datetime
class UpperPanel(wx.Panel):
def __init__(self, *args, **kwargs):
wx.Panel.__init__(self, *args, **kwargs)
#Timer
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.Update, self.timer)
#Enter Task Field
self.edit = wx.TextCtrl(self, -1, size=wx.Size(200, -1))
#Enter Task Button
self.button = wx.Button(self, -1, label="Enter!")
self.midpanel = MiddlePanel(self)
self.button.Bind(wx.EVT_BUTTON, self.midpanel.OnEnterPressed)
#Start/Stop Button
self.start_button=wx.Button(self, label="Start", size=(150,50))
self.Bind(wx.EVT_BUTTON, MiddlePanel.StartButton, self.start_button)
#Exit Button
self.exit_button=wx.Button(self, -1, label="Exit", size=(150,50))
self.Bind(wx.EVT_BUTTON, MainWin.CloseButton, self.exit_button)
self.sizer = wx.BoxSizer()
self.sizer.Add(self.edit, 1, wx.EXPAND)
self.sizer.Add(self.start_button, 0, wx.EXPAND)
self.sizer.Add(self.exit_button, 0, wx.EXPAND)
self.SetSizerAndFit(self.sizer)
#=====================================================================
class MiddlePanel(wx.Panel):
def __init__(self, *args, **kwargs):
wx.Panel.__init__(self, *args, **kwargs)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizerAndFit(self.sizer)
#Initialize Variables
self.box_height = 100
self.box_count = 0
self.start_time = ''
def OnEnterPressed(self, event):
#Get entered text
uppanel = UpperPanel(self)
self.box_label = uppanel.edit.GetValue()
if self.box_count < 10:
for x in range(0, 1):
chbx1 = wx.CheckBox(self, -1, self.box_label)
txtbx1 = wx.TextCtrl(self, -1)
self.box_height += 30
uppanel.edit.Clear()
print("CLEARED!")
print self.box_count
print uppanel.edit.GetValue()
#self.Layout()
self.box_count += 1
def StartButton(self,event):
self.start_time = datetime.datetime.now()
btn_label = self.start_button.GetLabel()
if btn_label == "Start":
print "starting timer..."
self.timer.Start(1000)
self.start_button.SetLabel("Stop")
else:
print "timer stopped!"
self.timer.Stop()
self.start_button.SetLabel("Start")
print ('Start button pressed.')
def Update(self, event):
seconds = (self.start_time - datetime.datetime.now() +
datetime.timedelta(days=1)).seconds
self.time_text.SetLabel('Time till next task:\n%d hours %d \
minutes %d seconds'
% (seconds / 3600,
(seconds / 60)
% (seconds / 3600 * 60),
seconds % 60))
#======================================================================
class MainWin(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
self.middlePanel = MiddlePanel(self)
self.upperPanel = UpperPanel(self)
self.textArea = wx.TextCtrl(self, size=(-1, 300), style=wx.TE_MULTILINE)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.upperPanel, 0, wx.EXPAND)
self.sizer.Add(self.middlePanel, 0, wx.EXPAND)
self.sizer.Add(self.textArea, 1, wx.EXPAND)
self.SetSizerAndFit(self.sizer)
#Window Closer
self.Bind(wx.EVT_CLOSE, self.CloseWindow)
#Create Menu Bar
status=self.CreateStatusBar()
menubar=wx.MenuBar()
firstmenu=wx.Menu()
secondmenu=wx.Menu()
firstmenu.Append(wx.NewId(),"Start","Starts the timer.")
firstmenu.Append(wx.NewId(),"Stop","Stops the timer.")
firstmenu.Append(wx.NewId(),"Exit","Exits the program.")
secondmenu.Append(wx.NewId(),"Preferences","Set the timer options.")
secondmenu.Append(wx.NewId(),"Edit task list",
"Add, change, or remove tasks.")
menubar.Append(firstmenu,"File")
menubar.Append(secondmenu,"Edit")
self.SetMenuBar(menubar)
#Static Text
self.st1 = wx.StaticText(self, -1, 'Enter Tasks:')
self.st2 = wx.StaticText(self, -1, 'Created by Spencer Evans')
self.time_text = wx.StaticText(self, -1, '')
def CloseButton(self,event):
#timer.Stop()
self.Close(True)
print ('Closed by Exit button.')
def CloseWindow(self,event):
#timer.Stop()
self.Destroy()
print ('Closed by X\'ing window.')
#========================================================================
#Run program
if __name__ == '__main__':
app = wx.PySimpleApp()
main_win = MainWin()
main_win.Show()
app.MainLoop()
I don't really know where your problem is. In my opinion all of the parts where already there, you just have to put them together. If I understood what you wanted, just replace the text field by a panel containing the text field and a button with a vertical sizer. Nice typing exercise, let me suggest a solution:
--- /tmp/test.py
+++ /tmp/test2.py
## -11,8 +11,19 ##
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.Update, self.timer)
+ # Panel for 'Enter Task' textfield and button
+ enter_task_panel = wx.Panel(self, -1)
+ task_panel_sizer = wx.BoxSizer(wx.VERTICAL)
+ enter_task_panel.SetSizer(task_panel_sizer)
+
#Enter Task Field
- self.edit = wx.TextCtrl(self, -1, size=wx.Size(200, -1))
+ self.edit = wx.TextCtrl(enter_task_panel, -1, size=wx.Size(200, -1))
+ task_panel_sizer.Add(self.edit, 1)
+
+ # 'Enter Task' button
+ enter_task_button = wx.Button(enter_task_panel, -1, "Enter Task")
+ task_panel_sizer.Add(enter_task_button, 1, wx.EXPAND)
+
#Enter Task Button
self.button = wx.Button(self, -1, label="Enter!")
self.midpanel = MiddlePanel(self)
## -25,7 +36,7 ##
self.Bind(wx.EVT_BUTTON, MainWin.CloseButton, self.exit_button)
self.sizer = wx.BoxSizer()
- self.sizer.Add(self.edit, 1, wx.EXPAND)
+ self.sizer.Add(enter_task_panel, 1, wx.EXPAND)
self.sizer.Add(self.start_button, 0, wx.EXPAND)
self.sizer.Add(self.exit_button, 0, wx.EXPAND)
Zetcode has a pretty good tutorial on wxPython, I can only recommend.

Categories