Related
so the goal here is to take an input from the user and display relevant data from an excel sheet.
Our problem is a rather minor, but irritating one...
When the input doesn't get a match from the database, we will display a message saying that the input number was invalid. We used a helper function to format the output to look like this
Here's the formatting code:
def makeRMAString(self, RMAnum, DMRnum, serial, status, cdate, udate):
rma_string = 'RMA#\t: {}\nDMR#\t: {} \nSerial#\t: {}\nStatus\t: {}\nCreated\t: {}\nUpdate\t: {}'
return rma_string.format(RMAnum, DMRnum, serial, status, cdate, udate)
Screenshot shows that all is well when the input matches something in the database. When it doesn't, we execute the following line:
self.rmaData.Label = self.makeRMAString('Invalid RMA number', '' , '', '', '', '')
And this is where the issue occurs; instead of having a nicely formatted output, the 'Invalid RMA number' gets pushed into the next line as if there was a nextline added in:
like this
I launched from command prompt to see the output, and it looks just fine there. Here's proof
We are using wxpython's BoxSizer to help:
self.rmaData = wx.StaticText(self.panel, wx.ID_ANY, self.makeRMAString('','','','','',''))
self.sizer_rmaHoriz = wx.BoxSizer(wx.HORIZONTAL)
self.sizer_rmaHoriz.Add(self.rmaData, 4, wx.ALIGN_LEFT|wx.CENTER, 15)
self.rmaData.SetFont(font)
We are using python 2.7.10
As requested a demo of a Grid sizer.
I've chosen a GridBagSizer, it seems the most appropriate to your requirement.
import wx
data = [
["99550","539761","016833-0695","Shipped","03/27/20","Unknown"],
["99551","539761","xxxxxx-xxxx","Shipped","03/22/20","Unknown"],
["99554","539761","016833-0695","Warehouse 1","01/12/19","Unknown"],
['Invalid RMA number','','','','','',''],
["99555","539761","777777-0695","Warehouse 2","02/27/20","Unknown"],
["99556","539761","016833-XXXX","Shipped","03/27/20","03/24/20"],
['Invalid RMA number','','','','','','']
]
class Example(wx.Frame):
def __init__(self, parent, title):
super(Example, self).__init__(parent, title = title)
self.InitUI()
self.Centre()
self.Show()
def InitUI(self):
self.idx = 0
panel = wx.Panel(self)
sizer = wx.GridBagSizer(0,0)
self.rma = wx.TextCtrl(panel,style=wx.TE_PROCESS_ENTER)
sizer.Add(self.rma, pos = (0, 1), flag = wx.ALIGN_CENTRE_VERTICAL)
EnterB = wx.Button(panel, label = "Enter RMA")
sizer.Add(EnterB, pos = (0,2),flag = wx.ALL, border = 5)
text = wx.StaticText(panel, label = "RMA :")
sizer.Add(text, pos = (1, 0), flag = wx.ALIGN_CENTRE_VERTICAL|wx.ALL, border = 5)
self.tc = wx.TextCtrl(panel, style=wx.TE_READONLY, size=(150,-1))
sizer.Add(self.tc, pos = (1, 1), flag = wx.EXPAND)
text1 = wx.StaticText(panel, label = "DMR :")
sizer.Add(text1, pos = (2, 0), flag = wx.ALIGN_CENTRE_VERTICAL|wx.ALL, border = 5)
self.tc1 = wx.TextCtrl(panel, style=wx.TE_READONLY)
sizer.Add(self.tc1, pos = (2,1), flag = wx.EXPAND)
text2 = wx.StaticText(panel,label = "Serial :")
sizer.Add(text2, pos = (3, 0), flag = wx.ALIGN_CENTRE_VERTICAL|wx.ALL, border = 5)
self.tc2 = wx.TextCtrl(panel, style=wx.TE_READONLY)
sizer.Add(self.tc2, pos = (3,1), flag = wx.EXPAND)
text3 = wx.StaticText(panel,label = "Status :")
sizer.Add(text3, pos = (4, 0), flag = wx.ALIGN_CENTRE_VERTICAL|wx.ALL, border = 5)
self.tc3 = wx.TextCtrl(panel, style=wx.TE_READONLY)
sizer.Add(self.tc3, pos = (4,1),flag = wx.EXPAND)
text4 = wx.StaticText(panel,label = "Created:")
sizer.Add(text4, pos = (5, 0), flag = wx.ALIGN_CENTRE_VERTICAL|wx.ALL, border = 5)
self.tc4 = wx.TextCtrl(panel, style=wx.TE_READONLY)
sizer.Add(self.tc4, pos = (5,1), flag = wx.EXPAND)
text5 = wx.StaticText(panel,label = "Update :")
sizer.Add(text5, pos = (6, 0), flag = wx.ALIGN_CENTRE_VERTICAL)
self.tc5 = wx.TextCtrl(panel, style=wx.TE_READONLY)
sizer.Add(self.tc5, pos = (6,1), flag = wx.EXPAND)
Next = wx.Button(panel, label = "Demo")
sizer.Add(Next, pos = (7, 1))
panel.SetSizerAndFit(sizer)
EnterB.Bind(wx.EVT_BUTTON, self.OnRma)
self.rma.Bind(wx.EVT_TEXT_ENTER, self.OnRma)
Next.Bind(wx.EVT_BUTTON, self.OnNext)
def OnRma(self, event):
rma = self.rma.GetValue()
idx = [i for i, e in enumerate(data) if e[0] == rma]
if idx:
self.idx = idx[0]
self.OnNext(None)
else:
self.tc.SetValue('Invalid RMA number')
self.tc1.SetValue('')
self.tc2.SetValue('')
self.tc3.SetValue('')
self.tc4.SetValue('')
self.tc5.SetValue('')
def OnNext(self, event):
self.rma.SetValue('')
self.tc.SetValue(data[self.idx][0])
self.tc1.SetValue(data[self.idx][1])
self.tc2.SetValue(data[self.idx][2])
self.tc3.SetValue(data[self.idx][3])
self.tc4.SetValue(data[self.idx][4])
self.tc5.SetValue(data[self.idx][5])
self.idx += 1
if self.idx > len(data) - 1:
self.idx = 0
app = wx.App()
Example(None, title = 'GridBag Demo')
app.MainLoop()
Useage:
input an RMA number (99550, 99551, 99554, 99555 or 99556) and press Enter or the Enter Rma button
enter some invalid RMA and press Enter or the Enter Rma button
Click the Demo button, it will scroll through the data
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.
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.
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.
I am creating a program to calculate D&D scores. I have all the backend done, and I want to get the GUI done now.
What I am trying to do here is have a static panel for certain buttons (next, previous, ok, cancel, etc.). The panel is not cooperating.
I want to try to get it on the bottom right (where next/previous buttons traditionally are). This panel can go in the notebook sizer or in the sizer sizerMain I have made for everything else in step_1.
Let me know if you have any questions. I am very new to wxPython and I hope you can deal with my code... :)
Code is below:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import wx
class step_1(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, id=wx.ID_ANY)
# Create initial sizers and panels
## Main sizer, containing both panels
sizerMain = wx.BoxSizer(wx.VERTICAL)
## For the main control area
panelControl = wx.Panel(self,2)
sizerControl = wx.GridBagSizer(hgap = 4,vgap = 4)
## For buttons
panelBtn = wx.Panel(self,1)
sizerBtn = wx.BoxSizer(wx.HORIZONTAL)
# Add widgets
## Main content area
lblTitle = wx.StaticText(self,label = "Pick Scores")
sizerControl.Add(lblTitle,pos = (0,0),
flag = wx.ALIGN_CENTER|wx.TOP|wx.LEFT|wx.BOTTOM,
border = 5)
btnRoll = wx.Button(self,label = "Roll!")
sizerControl.Add(btnRoll,pos = (0,1),span = (1,5),
flag = wx.EXPAND|wx.ALL,border = 5)
### Radio boxes
#### Radio button tuple
rboxPick = ["Default","Strength","Dexterity","Constitution",
"Intelligence","Wisdom","Charisma"]
self.lblRoll1 = wx.StaticText(self,label = "0")
sizerControl.Add(self.lblRoll1,pos = (1,0),flag = wx.ALIGN_CENTER)
self.rboxRoll1 = wx.RadioBox(self,label = "Roll One",choices = rboxPick)
sizerControl.Add(self.rboxRoll1,pos = (1,1),span = (1,5),
flag = wx.EXPAND|wx.LEFT|wx.RIGHT,border = 2)
self.lblRoll2 = wx.StaticText(self,label = "0")
sizerControl.Add(self.lblRoll2,pos = (2,0),flag = wx.ALIGN_CENTER)
self.rboxRoll2 = wx.RadioBox(self,label = "Roll Two",choices = rboxPick)
sizerControl.Add(self.rboxRoll2,pos = (2,1),span = (1,5),
flag = wx.EXPAND|wx.LEFT|wx.RIGHT,border = 2)
self.lblRoll3 = wx.StaticText(self,label = "0")
sizerControl.Add(self.lblRoll3,pos = (3,0),flag = wx.ALIGN_CENTER)
self.rboxRoll3 = wx.RadioBox(self,label = "Roll Three",choices = rboxPick)
sizerControl.Add(self.rboxRoll3,pos = (3,1),span = (1,5),
flag = wx.EXPAND|wx.LEFT|wx.RIGHT,border = 2)
self.lblRoll4 = wx.StaticText(self,label = "0")
sizerControl.Add(self.lblRoll4,pos = (4,0),flag = wx.ALIGN_CENTER)
self.rboxRoll4 = wx.RadioBox(self,label = "Roll Four",choices = rboxPick)
sizerControl.Add(self.rboxRoll4,pos = (4,1),span = (1,5),
flag = wx.EXPAND|wx.LEFT|wx.RIGHT,border = 2)
self.lblRoll5 = wx.StaticText(self,label = "0")
sizerControl.Add(self.lblRoll5,pos = (5,0),flag = wx.ALIGN_CENTER)
self.rboxRoll5 = wx.RadioBox(self,label = "Roll Five",choices = rboxPick)
sizerControl.Add(self.rboxRoll5,pos = (5,1),span = (1,5),
flag = wx.EXPAND|wx.LEFT|wx.RIGHT,border = 2)
self.lblRoll6 = wx.StaticText(self,label = "0")
sizerControl.Add(self.lblRoll6,pos = (6,0),flag = wx.ALIGN_CENTER)
self.rboxRoll6 = wx.RadioBox(self,label = "Roll Six",choices = rboxPick)
sizerControl.Add(self.rboxRoll6,pos = (6,1),span = (1,5),
flag = wx.EXPAND|wx.LEFT|wx.RIGHT,border = 2)
### Instructions
self.tcLogger = wx.TextCtrl(self,style = wx.TE_MULTILINE)
sizerControl.Add(self.tcLogger,pos = (7,0),span = (1,6),
flag = wx.EXPAND|wx.LEFT|wx.RIGHT,border = 5)
self.tcLogger.AppendText("""Instructions
1. Click the "Roll!" button up top.
- Scores will be placed in the empty slots on the left side.
2. Look at the scores and decide where you want to put them.
3. Click the correct label for each score.
- Make sure you only assign one score to one ability.
4. Click "Assign" to finalize the assignment.""")
## Button area
self.btnPrev = wx.Button(self,label = "Previous",size = (90,28))
self.btnAssign = wx.Button(self,label = "Assign",size = (90,28))
self.btnNext = wx.Button(self,label = "Next",size = (90,28))
sizerBtn.Add(self.btnPrev)
sizerBtn.Add(self.btnAssign)
sizerBtn.Add(self.btnNext,flag = wx.RIGHT|wx.BOTTOM,border = 5)
self.btnNext.Disable()
self.btnPrev.Disable()
# Set and fit sizers, panels, etc.
## Growable rows and columns
sizerControl.AddGrowableCol(1)
sizerControl.AddGrowableRow(7)
## Finalize sizers and panels
panelControl.SetSizerAndFit(sizerControl)
panelBtn.SetSizerAndFit(sizerBtn)
### Final sizer to hold everything
sizerMain.Add(panelControl,2,wx.EXPAND|wx.ALIGN_TOP|wx.ALL,border = 5)
sizerMain.Add(panelBtn,1,wx.EXPAND|wx.ALIGN_BOTTOM|wx.RIGHT,border = 5)
self.SetAutoLayout(True)
self.SetSizerAndFit(sizerMain)
self.Layout()
# Bind events (as needed)
class step_2(wx.Panel):
def __init__(self, parent):
""""""
wx.Panel.__init__(self, parent, id=wx.ID_ANY)
sizer = wx.BoxSizer(wx.VERTICAL)
txtOne = wx.TextCtrl(self, wx.ID_ANY, "")
txtTwo = wx.TextCtrl(self, wx.ID_ANY, "")
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(txtOne, 0, wx.ALL, 5)
sizer.Add(txtTwo, 0, wx.ALL, 5)
self.SetSizer(sizer)
class step_3(wx.Panel):
def __init__(self, parent):
""""""
wx.Panel.__init__(self, parent, id=wx.ID_ANY)
sizer = wx.BoxSizer(wx.VERTICAL)
txtOne = wx.TextCtrl(self, wx.ID_ANY, "")
txtTwo = wx.TextCtrl(self, wx.ID_ANY, "")
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(txtOne, 0, wx.ALL, 5)
sizer.Add(txtTwo, 0, wx.ALL, 5)
self.SetSizer(sizer)
####
# create a button class here for later, don't worry about it now
####
class main_frame(wx.Frame):
"""Main Frame holding the main panel."""
def __init__(self,*args,**kwargs):
wx.Frame.__init__(self,*args,**kwargs)
# Build the menu bar
menuBar = wx.MenuBar()
menuFile = wx.Menu()
menuFileQuit = menuFile.Append(wx.ID_EXIT, text="&Quit")
#self.Bind(wx.EVT_MENU, self.OnQuit,menuFileQuit)
menuBar.Append(menuFile, "&File")
self.SetMenuBar(menuBar)
p = wx.Panel(self)
nb = wx.Notebook(p)
# create the page windows as children of the notebook
nbPage1 = step_1(nb)
nbPage2 = step_2(nb)
nbPage3 = step_3(nb)
# add the pages to the notebook with the label to show on the tab
nb.AddPage(nbPage1,"Page 1")
nb.AddPage(nbPage2,"Page 2")
nb.AddPage(nbPage3,"Page 3")
# finally, put the notebook in a sizer for the panel to manage the
# layout
sizer = wx.BoxSizer()
sizer.Add(nb, 1, wx.EXPAND)
p.SetSizer(sizer)
self.Center()
self.Show()
if __name__ == "__main__":
app = wx.App(False)
frame = main_frame(None,-1,size = (1000,1000),title = "D&D Charcter Creator")
app.MainLoop()
You've got parenting problems!
For example, you want the widget self.lblRoll1 to be on the panelControl therefore you should make it a child of it.
e.g.
self.lblRoll1 = wx.StaticText(panelControl,label = "0")
This is your problem -it occurs throughout your code.
An indispensable tool for solving these type of issues is the Widget Inspection tool.
Also Id advise you to factor out the code for each panel into its own class (which would subclass wx.Panel). This will make it all much easier to read and maintain.