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
Related
I am making a budgeting program that displays all the user's expenses. I want to have it so that when the user clicks on the ListUI, it displays all the data about the category. I can get the program to switch between two category panels, however I can't get the Summary page to display properly. It is just blank without any information.
(Bonus points for positioning the panels beside the List UI, something I want to learn buy haven't gotten to yet.)
#In my budget module
def displayBudget(self,panel,sizer):
self.categoryListUI = wx.ListCtrl(panel, wx.ID_ANY,style = wx.LC_REPORT)
self.categoryPanelList = []
self.categoryListUI.InsertColumn(0, 'Name',width = 75)
self.categoryListUI.InsertColumn(1, 'Amount',width = 100)
self.categoryListUI.InsertColumn(2, 'Spending',width = 100)
self.categoryListUI.InsertColumn(3, 'Remaining',width = 100)
index = 0
self.insertListCtrlSummary(self.categoryListUI,index,panel)
tempCatPanel = self.displaySummary(panel)
tempCatPanel.Hide()
self.categoryPanelList.append(tempCatPanel)
index += 1
for i in self.categoryArray:
i.insertListCtrl(self.categoryListUI,index,panel)
tempCatPanel = i.displayCategory(panel)
tempCatPanel.Hide()
self.categoryPanelList.append(tempCatPanel)
index += 1
panel.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnClick, self.categoryListUI)
sizer.Add(self.categoryListUI,pos=(2, 0),span=(1, 100),flag = wx.EXPAND|wx.ALIGN_LEFT|wx.ALIGN_BOTTOM, border = 5)
self.currentPanel = self.categoryPanelList[0]
self.currentPanel.Update()
self.currentPanel.Show()
sizer.Add(self.currentPanel ,pos=(25, 25),span=(4, 8),flag = wx.EXPAND|wx.ALIGN_RIGHT|wx.ALL, border = 5)
panel.SetSizerAndFit(sizer)
print(len(self.categoryPanelList))
return sizer
def OnClick(self,event):
if self.currentPanel != None:
self.currentPanel.Hide()
print(event.GetIndex())
self.currentPanel = self.categoryPanelList[event.GetIndex()]
if self.currentPanel is None:
wx.MessageBox('Could not display Category.', 'Error', wx.OK | wx.ICON_ERROR)
else:
self.currentPanel.Update()
self.currentPanel.Show()
def insertListCtrlSummary(self,uiList,index,panel):
self.categoryListUI.InsertItem(index, "Summary")
self.categoryListUI.SetItem(index, 1, "$ "+str(format(self.amount, '.2f')))
self.categoryListUI.SetItem(index, 2, "$ "+str(format(self.totalSpending(), '.2f')))
self.categoryListUI.SetItem(index, 3, "$ "+str(format(self.totalRemaining(), '.2f') ))
def displaySummary(self,parent):
panel = wx.Panel(parent)
sizer = wx.GridBagSizer(5, 5)
remainString = "Remaining: $ "+str(self.totalRemaining())
remainStatic = wx.StaticText(panel, wx.ID_ANY, remainString)
amountStatic = wx.StaticText(panel, wx.ID_ANY, "Amount: $ ")
amountDisplay = wx.TextCtrl(panel, wx.ID_ANY, str(self.amount))
sizer.Add(amountStatic,pos=(0, 0),span=(1, 1),flag = wx.EXPAND|wx.ALIGN_LEFT, border = 5)
sizer.Add(amountDisplay,pos=(0, 1),span=(1, 1),flag = wx.EXPAND|wx.ALIGN_LEFT, border = 5)
sizer.Add(remainStatic,pos=(0, 4),span=(1, 3),flag = wx.EXPAND|wx.ALIGN_LEFT, border = 5)
panel.SetSizerAndFit(sizer)
panel.Show()
return panel
#Category display stuff.
def insertListCtrl(self,uiList,index,panel):
uiList.InsertItem(index, self.name)
uiList.SetItem(index, 1, "$ "+str(format(self.amount, '.2f')))
uiList.SetItem(index, 2, "$ "+str(format(self.calculateExpenses(), '.2f')))
uiList.SetItem(index, 3, "$ "+str(format(self.calculateRemainingAmount(), '.2f')))
def displayCategory(self,panelMaster):
panel = wx.Panel(panelMaster)
sizer = wx.GridBagSizer(5, 5)
remainString = "Remaining: $ "+ str(format(self.calculateRemainingAmount(), '.2f'))
remainStatic = wx.StaticText(panel, wx.ID_ANY, remainString)
amountStatic = wx.StaticText(panel, wx.ID_ANY, "Amount: $ ")
amountDisplay = wx.TextCtrl(panel, wx.ID_ANY, str(format(self.amount, '.2f')))
sizer.Add(amountStatic,pos=(0, 0),span=(1, 1),flag = wx.EXPAND|wx.ALIGN_LEFT, border = 5)
sizer.Add(amountDisplay,pos=(0, 1),span=(1, 1),flag = wx.EXPAND|wx.ALIGN_LEFT, border = 5)
sizer.Add(remainStatic,pos=(0, 4),span=(1, 3),flag = wx.EXPAND|wx.ALIGN_LEFT, border = 5)
panel.SetSizerAndFit(sizer)
return panel
I have an application that produces a popup window containing a progress bar. The code related to the popup window is below. I would like to force this popup window to stay on top of the application that produces this window. I tried using wx.STAY_ON_TOP, but using this style forces the popup window to stay on top of all applications, which is not what I want. Any advice/suggestion would be appreciated!
class ProgressBar(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, None, title="In progress...",
size=(300, 125))
GridBagSizer = wx.GridBagSizer()
TextFont = wx.Font(pointSize = 9, family = wx.SWISS, style = wx.NORMAL, weight = wx.NORMAL, faceName = 'Tahoma')
self.SetBackgroundColour('white')
self.gauge = wx.Gauge(self, range = 100, size = (-1, 30), style = wx.GA_HORIZONTAL, name = 'In Progress')
self.gauge.SetValue(0)
GridBagSizer.Add(self.gauge, pos = (0, 0), span = (1, 1), flag = wx.EXPAND|wx.ALL, border = 15)
self.txt = wx.StaticText(self, label = 'Retrieving data...', style = wx.ALIGN_CENTER)
self.txt.SetFont(TextFont)
box = wx.BoxSizer(wx.HORIZONTAL)
box.Add(self.txt, 0, wx.CENTER)
GridBagSizer.Add(box, pos = (1, 0), span = (1, 1),
flag = wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM,
border = 15)
GridBagSizer.AddGrowableCol(0)
#GridBagSizer.AddGrowableCol(1)
self.SetSizer(GridBagSizer)
self.SetMinSize((300, 125))
self.SetMaxSize((300, 125))
self.Layout()
self.Center()
def Update(self, step):
self.gauge.SetValue(step)
if step == 100:
self.Close()
def SetLabel(self, label):
self.txt.SetLabel(label)
self.Refresh()
self.Layout()
use style wx.FRAME_FLOAT_ON_PARENT
class ProgressBar(wx.Frame):
def __init__(self, parent): # you must set the parent ...
wx.Frame.__init__(self, parent, title="In progress...",
size=(300, 125),style=wx.FRAME_FLOAT_ON_PARENT)
...
if you want it to have the default frame stuff you can do
style=wx.DEFAULT_FRAME_STYLE|wx.FRAME_FLOAT_ON_PARENT
I am using wx.TextDropTarget to implement a drag and drop app where users can drag some text strings from a ListCtrl widget and drop them into TextCtrl widgets. One problem that I haven’t been able to figure out how to solve is that sometimes text strings dropped in TextCtrl widgets have random characters appended to the end (see screenshot below). This problem does not arise every single time – as you can see, “East of Eden” is displayed fine.
I am on OSX 10.10.5 and using wxPython 2.9.2.4-1. I am not sure if this problem can be reproduced on other platforms. A sample code is below.
import wx
from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
class AutoWidthListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin):
def __init__(self, parent):
wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT)
ListCtrlAutoWidthMixin.__init__(self)
class TextDropTarget(wx.TextDropTarget):
def __init__(self, obj):
wx.TextDropTarget.__init__(self)
self.obj = obj
def OnDropText(self, x, y, text):
self.obj.WriteText(text)
def OnDragOver(self, x, y, d):
return wx.DragCopy
class MyApp(wx.Frame):
def __init__(self, parent, title):
super(MyApp, self).__init__(parent, style = wx.DEFAULT_FRAME_STYLE,
title=title, size=(500, 500))
self.Panel = wx.Panel(self, size = (-1, -1))
GridBagSizer = wx.GridBagSizer(5,5)
#ListCtrl widget
self.Source = AutoWidthListCtrl(self.Panel)
self.Source.Show()
self.Source.InsertColumn(0, 'Book Titles')
self.Source.InsertStringItem(0,'War and Peace')
self.Source.InsertStringItem(0,'East of Eden')
self.Source.InsertStringItem(0,'Pride and Prejudice')
GridBagSizer.Add(self.Source, pos = (0, 0), span = (6, 1),
flag = wx.EXPAND|wx.ALL, border = 15)
self.Panel.SetSizer(GridBagSizer)
#Label for each TextCtrl widget
AmericanNovel = wx.StaticText(self.Panel, label ="American Novel:")
EnglishNovel = wx.StaticText(self.Panel, label = "British Novel:")
RussianNovel = wx.StaticText(self.Panel, label = "Russian Novel:")
GridBagSizer.Add(AmericanNovel, pos = (0, 1), span = (1, 1),
flag = wx.TOP, border = 10)
GridBagSizer.Add(EnglishNovel, pos = (2, 1), span = (1, 1))
GridBagSizer.Add(RussianNovel, pos = (4, 1), span = (1, 1))
#TextCtrl widgets
self.Target1 = wx.TextCtrl(self.Panel, size = (240, -1),
style = wx.TE_READONLY)
self.Target2 = wx.TextCtrl(self.Panel, size = (240, -1),
style = wx.TE_READONLY)
self.Target3 = wx.TextCtrl(self.Panel, size = (240, -1),
style = wx.TE_READONLY)
GridBagSizer.Add(self.Target1, pos = (1, 1), span = (1, 1))
GridBagSizer.Add(self.Target2, pos = (3, 1), span = (1, 1))
GridBagSizer.Add(self.Target3, pos = (5, 1), span = (1, 1))
dt1 = TextDropTarget(self.Target1)
dt2 = TextDropTarget(self.Target2)
dt3 = TextDropTarget(self.Target3)
self.Target1.SetDropTarget(dt1)
self.Target2.SetDropTarget(dt2)
self.Target3.SetDropTarget(dt3)
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.OnDragInit)
GridBagSizer.AddGrowableCol(0)
GridBagSizer.AddGrowableCol(1)
def OnDragInit(self, evt):
text = self.Source.GetItemText(evt.GetIndex())
tdo = wx.TextDataObject(text)
tds = wx.DropSource(self.Source)
tds.SetData(tdo)
tds.DoDragDrop(True)
if __name__ == "__main__":
app = wx.App()
MainFrame = MyApp(None, title = "My App")
MainFrame.Show()
MainFrame.Centre()
app.MainLoop()
Any pointer would be much appreciated!
Your code works on Linux.
The only thing that I can see, that differs from the standard examples, is your code:
tdo = wx.TextDataObject(text)
should be:
tdo = wx.PyTextDataObject(text)
although, with Linux it does not appear to matter.
EDIT:
First, see this link which appears to be related:
wx.PyTextDataObject with drag and drop results in extra characters
Second:
As a work-around, try adding this after defining text
text = text.decode('iso-8859-1').encode('ascii', 'ignore')
It's an attempt to remove the extraneous characters.
You could try printing them out as a raw string:
print (repr(text))
does anyone of you have an example how to make the following possible:
I have a listctrl that displays > 600 items. Now I need to search in these items for a text the user inputs and update the list to only show the items containing this string.
So let us say the list contains "Hello", "Hi" and "Morning". The list displays all three items. Now the user types "h" into the textctrl, and the listctrl is narrowed down to "Hello" and "Hi". If the user instead types "o", and the list becomes "Hello" and "Morning".
Is this possible? Or is there any other convenient way to find an item in a listctrl? The build in "find as you type" is only of real use if you do exactly know what you search for - and in my case this will not really be the case...
Thanks, Woodpicker
The wxPython demo has a pretty good "type-ahead" filter built into it. Looking at the source code to Main.py they do it the "manual way", loop and rebuild the list. They are using a treeview but the ideas are sound:
def OnSearch(self, event=None):
value = self.filter.GetValue()
if not value:
self.RecreateTree()
return
wx.BeginBusyCursor()
for category, items in _treeList:
self.searchItems[category] = []
for childItem in items:
if SearchDemo(childItem, value):
self.searchItems[category].append(childItem)
wx.EndBusyCursor()
self.RecreateTree()
I like the ObjectListView wrapper better than the straight wx.ListCtrl. It includes the ability to filter items in the control as a feature of the widget. You can read about it here: http://objectlistview.sourceforge.net/python/features.html#filtering and here's the main page for the control: http://objectlistview.sourceforge.net/python/
Here is an example of filtering an UltimateListCtrl.
I know this is 2 years later but I've found other examples on stackoverflow really, really helpful.
I'm new to python/wxpython but hopefully it will be useful.
starting from http://www.blog.pythonlibrary.org/2011/11/02/wxpython-an-intro-to-the-ultimatelistctrl/
import wx
from wx.lib.agw import ultimatelistctrl as ULC
class ULC_Panel(wx.Panel):
""""""
def __init__(self, parent, col_headers=None, list_data=None, options=None, dlg=None,
selected_list=None):
"""Constructor"""
wx.Panel.__init__(self, parent)
self.options = options
self.show_only_selected = False
self.filter_string = ""
hsizer = wx.BoxSizer(wx.HORIZONTAL)
okayButton = wx.Button(self, wx.ID_OK, "OK")
okayButton.SetToolTip(wx.ToolTip("Click to close this dialog and use the selections"))
self.Bind(wx.EVT_BUTTON, self.OnOkayCanButton, okayButton)
hsizer.Add(okayButton, 0, wx.ALL, 5)
canButton = wx.Button(self, wx.ID_CANCEL, "Cancel")
canButton.SetToolTip(wx.ToolTip("Click to close this dialog and cancel selections"))
self.Bind(wx.EVT_BUTTON, self.OnOkayCanButton, canButton)
hsizer.Add(canButton, 0, wx.ALL, 5)
cb_show_only = wx.CheckBox(self, -1, "Show only selected items?")
cb_show_only.SetValue(self.show_only_selected)
cb_show_only.SetToolTip(wx.ToolTip("Click to show only selected rows"))
self.Bind(wx.EVT_CHECKBOX, self.EvtShowOnly, cb_show_only)
hsizer.Add(cb_show_only, 0, wx.ALL, 5)
self.stext = wx.StaticText(self, -1, "Filter: ", style=wx.ALIGN_LEFT)
self.filtr = wx.TextCtrl(self, -1, "", style=wx.ALIGN_LEFT)
self.Bind(wx.EVT_TEXT, self.OnFiltr, self.filtr)
fsizer = wx.BoxSizer(wx.HORIZONTAL)
fsizer.Add(self.stext, 0, wx.ALL)
fsizer.Add(self.filtr, 1, wx.EXPAND)
font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
boldfont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
boldfont.SetWeight(wx.BOLD)
boldfont.SetPointSize(12)
self.ultimateList = ULC.UltimateListCtrl(self, agwStyle = wx.LC_REPORT
| wx.LC_VRULES | ULC.ULC_HAS_VARIABLE_ROW_HEIGHT
| wx.LC_HRULES)
self.checkbox = [None] * len(list_data)
if selected_list != None:
self.selected = selected_list
else:
self.selected = [False] * len(list_data)
self.rows_max = len(list_data)
self.rows_current = -1
self.cols_max = len(col_headers)
self.cols_extra = 1
if options & ULC.ULC_MASK_CHECK:
self.cols_extra += 1
for i in xrange(self.cols_max+self.cols_extra):
info = ULC.UltimateListItem()
info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT
info._image = []
info._format = 0
info._kind = 1
width = 150
if i >= self.cols_extra:
info._text = col_headers[i-self.cols_extra]
elif i == 0:
info._text = "Row"
width = 35
elif i == 1 and options & ULC.ULC_MASK_CHECK:
info._text = "Select"
width = 50
self.ultimateList.InsertColumnInfo(i, info)
self.ultimateList.SetColumnWidth(i, width)
self.list_data = list_data
pos = self.populate_table("")
if pos != None:
self.sz = self.ultimateList.GetItemRect(pos)
self.width = self.sz[2] + self.sz[3]
self.height = self.sz[1]
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(hsizer, 0, wx.EXPAND)
sizer.Add(fsizer, 0, wx.EXPAND)
sizer.Add(self.ultimateList, 1, flag=wx.EXPAND)
self.SetSizer(sizer)
sizer.Fit(self)
def EvtShowOnly(self, event):
cb = event.GetEventObject()
val = cb.GetValue()
self.show_only_selected = val
pos = self.populate_table(self.filter_string)
print "show_only_selected val= ", val
def EvtCheckBox(self, event):
cb = event.GetEventObject()
id = event.GetId()
val = cb.GetValue()
self.selected[id] = val
print "id, val= ", id, val
def OnOkayCanButton(self, event):
id = event.GetId()
dlg.EndModal(id)
def myGetNeedWH(self):
return (self.width, self.height)
def myGetSelectedState(self):
return self.selected
def populate_table(self, str_in):
busy = wx.BusyCursor()
if str_in:
str_low = str_in.lower()
if self.options & ULC.ULC_MASK_CHECK:
# if we have widgets in the row then we have to delete 1 row
# at a time (or else it leaves some of the widgets)
i = self.rows_current
#print "i, self.rows_max= ", i, self.rows_max
while i >= 0:
#print "i= ", i
self.ultimateList.DeleteItem(i)
i -= 1
else:
self.ultimateList.DeleteAllItems()
row = -1
for i in xrange(len(self.list_data)):
tlwr = self.list_data[i][0].lower()
if not str_in or tlwr.find(str_low) >= 0:
if self.show_only_selected and self.selected[i] == False:
continue
row += 1
for j in xrange(self.cols_max+self.cols_extra):
if j == 0:
pos = self.ultimateList.InsertStringItem(row, str(row))
elif j == 1 and self.options & ULC.ULC_MASK_CHECK:
self.checkbox[i] = wx.CheckBox(self.ultimateList, id= i)
self.checkbox[i].SetValue(self.selected[i])
self.checkbox[i].SetToolTip(wx.ToolTip("Click to select this row"))
self.Bind(wx.EVT_CHECKBOX, self.EvtCheckBox, self.checkbox[i])
self.ultimateList.SetItemWindow(pos, col=1, wnd=self.checkbox[i], expand=False)
else:
self.ultimateList.SetStringItem(row, j, self.list_data[i][j-self.cols_extra])
self.rows_current = row
return row
def OnFiltr(self, event):
str1 = event.GetString()
id = event.GetId()
#print "got txt_tval str[%s]= %s" % (id, str1)
self.filter_string = str1
pos = self.populate_table(str1)
event.Skip()
return
########################################################################
class FilterListDiag(wx.Dialog):
def __init__(self, parent, id, title, headers=None, data_table=None, options=None, selected_list=None):
wx.Dialog.__init__(self, parent, id, title="", style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
options_in = options
self.panel = ULC_Panel(self, col_headers=headers, list_data=data_table, options=options_in,
dlg=self, selected_list=selected_list)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.panel, 1, wx.EXPAND)
self.SetSizer(sizer)
(self.width, self.height) = self.panel.myGetNeedWH()
def myGetNeedWH(self):
return (self.width, self.height)
def myGetSelectedState(self):
return self.panel.myGetSelectedState()
class TestFrame(wx.Frame):
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="MvP UltimateListCtrl Demo", size=(850,600))
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.App(False)
frame = TestFrame()
col_headers = ['col0', 'col1', 'col2']
list_data = [
["Newsboys", "Go", "Rock"],
["Puffy", "Bring It!", "Pop"],
["Family Force 5", "III", "Pop"],
["Me2", "III", "Pop"],
["Duffy", "III", "Pop"],
["Fluffy", "III", "Pop"],
]
# sel_data passes in a list of which rows are already selected
sel_data = [
False,
False,
False,
False,
True,
False,
]
opt=ULC.ULC_MASK_CHECK # just reusing this to indicate I want a column of checkboxes.
dlg = FilterListDiag(frame, -1, "hi", headers=col_headers, data_table=list_data, options=opt, selected_list=sel_data)
(w, h) = dlg.myGetNeedWH()
print w,h
dlg.SetSizeWH(w, 300)
val = dlg.ShowModal()
selected = dlg.myGetSelectedState()
print "okay, can, val= ", wx.ID_OK, wx.ID_CANCEL, val
dlg.Destroy()
print 'selected=', selected
I have something different.
I created a dictionary and updated every time there is an entry in the list ctrl. Now, when I have a search box, which changes the list ctrl with each input from the keyboard and I clear and re-update my dictionary. This way, I always have the latest index for the values.
Code is as below:
class ViewUserDialog(wx.Dialog):
def __init__(self):
title = 'View Users Records'
super().__init__(parent=None, size=(750, 600), title=title)
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
self.list_sizer = wx.BoxSizer(wx.VERTICAL)
self.row_obj_dict = {}
.
.
.
self.list_ctrl_View_User.InsertColumn(0, "ID", width=150)
self.list_ctrl_View_User.InsertColumn(1, "User Name", width=150)
for index, users in original_user_frame.iterrows():
self.list_ctrl_View_User.InsertItem(indexes, user_id_value)
self.list_ctrl_View_User.SetItem(indexes, 1, users.NAME)
user_objects.append(users)
self.row_obj_dict[indexes] = users
indexes += 1
Now on searching, and selecting an item in lstctrl, you will still get your results:
def on_view(self, event):
selection = self.list_ctrl_View_User.GetFocusedItem()
self.list_ctrl_View_User.ClearAll()
if selection >= 0:
user = self.row_obj_dict[selection]
print(user)
self.list_ctrl_View_User.InsertColumn(0, "ID", width=150)
self.list_ctrl_View_User.InsertColumn(1, "User Name", width=150)
for index, users in original_user_frame.iterrows():
self.list_ctrl_View_User.InsertItem(indexes, user_id_value)
self.list_ctrl_View_User.SetItem(indexes, 1, users.NAME)
This will always give the currect selected item from the lstctrl and update the list with every input.
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.