I need a ListBox to show a phone book.Then i need to show name in top and number in bottom in each list item like phone.how to bind the datas into listbox.
now i made a listbox with singleline as shown below
cur.execute("select fname from tblsample1 order by fname")
names = [str(item[0]) for item in cur.fetchall()]
lvnames=wx.ListBox(panel,-1,(10,40),(210,180),names, wx.LB_SINGLE)
how to bind sqlite3 cursor with two columns to the listview
i need a wx.ListBox mouse click event(not EVT_LISTBOX
because i need only mouse click event)
Use the HtmlListBox, here is a little example to get you started.
import wx
class PhoneNumbers(wx.HtmlListBox):
def __init__(self, parent):
wx.HtmlListBox.__init__(self, parent)
self.data = [
("Foo", "3452-453"),
("Bar", "5672-346"),
]
self.SetItemCount(len(self.data))
def OnGetItem(self, n):
return "<b>%s</b><br>%s" % self.data[n]
def add_number(self, name, number):
self.data.append((name, number))
self.SetItemCount(len(self.data))
self.Refresh()
class Frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, size=(200, 400))
self.numbers = PhoneNumbers(self)
self.contact_name = wx.TextCtrl(self)
self.contact_number = wx.TextCtrl(self)
self.add_btn = wx.Button(self, label="Add contact")
self.Sizer = wx.BoxSizer(wx.VERTICAL)
self.Sizer.Add(self.numbers, 1, wx.EXPAND)
self.Sizer.Add(wx.SearchCtrl(self), 0, wx.EXPAND)
self.Sizer.Add(wx.StaticText(self, label="Name"), 0, wx.TOP, 10)
self.Sizer.Add(self.contact_name)
self.Sizer.Add(wx.StaticText(self, label="Number"), 0, wx.TOP, 5)
self.Sizer.Add(self.contact_number)
self.Sizer.Add(self.add_btn, 0, wx.ALL, 10)
self.numbers.Bind(wx.EVT_LISTBOX, self.OnSelectNumber)
self.add_btn.Bind(wx.EVT_BUTTON, self.OnAddNumber)
def OnSelectNumber(self, event):
name, number = self.numbers.data[event.Selection]
self.contact_name.Value = name
self.contact_number.Value = number
def OnAddNumber(self, event):
self.numbers.add_number(
self.contact_name.Value,
self.contact_number.Value
)
app = wx.PySimpleApp()
app.TopWindow = f = Frame()
f.Show()
app.MainLoop()
You should rephrase your question, I don't know if I got this right.
If you only need to display the two lines in your ListBox, you could simply use a \n:
cur.execute("select fname,number from tblsample1 order by fname")
entries = [str(item[0])+'\n'+str(item[1]) for item in cur.fetchall()]
To get a 'click' Event, you cant set the style of your wx.ListBox to wx.LC_SINGLE_SEL and catch the selection event wx.EVT_LIST_ITEM_SELECTED
Related
Greetings to the respected community!
I have the following task: I need to create a panel with buttons whose names are taken from the file (all_classes). When clicking on each label, the buttons must be recorded in another file (chosen_classes). I managed to create buttons in the loop and arrange them on the panel, but the recording event to the button is not tied and I do not understand why.
all_classes = open('data/yolo2/yolo2.names', 'r').read().split()
chosen_classes = open('chosen_classes', 'w')
deltaxSize, deltaySize, c = 0, 0, 0
for k, obj_class in enumerate(all_classes):
self.buttons.append(wx.Button(self.panel, label=f'{obj_class}', pos=(50 + deltaxSize, 20 + deltaySize),
size=(100, 20)))
self.Bind(wx.EVT_BUTTON, lambda event: chosen_classes.write(f'{obj_class}\n'), self.buttons[k])
deltaySize += 20
c += 1
if c == 30:
deltaxSize += 100
deltaySize, c = 0, 0
I tried instead of recording in the lambda just prints to check what was going on, but got a strange result: when you press any button, only the last label is displayed:
deltaxSize, deltaySize, c = 0, 0, 0
self.buttons = []
for k, obj_class in enumerate(all_classes):
self.buttons.append(wx.Button(self.panel, label=f'{obj_class}', pos=(50 + deltaxSize, 20 + deltaySize),
size=(100, 20)))
self.Bind(wx.EVT_BUTTON, lambda event: print(f'{obj_class}\n'), self.buttons[k])
deltaySize += 20
c += 1
if c == 30:
deltaxSize += 100
deltaySize, c = 0, 0
The same happens if you replace obj_class in the f-line with self.buttons [k]. GetLabelText () At the same time, if you turn to each button separately outside the loop, you can print the label, but the file still does not record. I am completely, admittedly, perplexed, if anyone can suggest anything, I would be infinitely grateful. Thanks.
You have managed to over complicate your solution a bit.
The use of a sizer will make this easier and because the only event being fired is a button event and they all do the same thing, we only need to bind it once.
Pick the bones out of the following, it should help.
import wx
all_classes = ["abc","def","ghi","jkl","mno","pqr","stu","vwx","yz"]
chosen_classes = open('chosen_classes.txt', 'w')
class ButtonPanel(wx.Panel):
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.sizer)
self.parent = parent
for k, obj_class in enumerate(all_classes):
self.add_button(obj_class)
self.Bind(wx.EVT_BUTTON, self.OnButton)
self.parent.Layout()
def add_button(self, obj_class):
self.sizer.Add(wx.Button(self, label=f'{obj_class}'), 0, wx.EXPAND, 0)
def OnButton(self,event):
obj = event.GetEventObject()
label = obj.GetLabel()
chosen_classes.write(label+" Pressed\n")
print(label)
class MyPanel(wx.Panel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.button_panel = ButtonPanel(self)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self.button_panel, 0, wx.EXPAND, 0)
self.SetSizer(sizer)
class MyFrame(wx.Frame):
def __init__(self, *args):
super().__init__(*args)
panel = MyPanel(self)
app = wx.App()
frame = MyFrame(None)
frame.Show()
app.MainLoop()
I am developing a wxpython, i am looking for button generating, for example.
In text box enter the value how many button have to generate.
While submitting that, i have to show in panel as many as button
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Background Reset Tutorial",size=wx.Size(500,500))
# Add a panel so it looks the correct on all platforms
self.panel = wx.Panel(self, wx.ID_ANY)
self.txt = wx.TextCtrl(self.panel,id=wx.ID_ANY,pos=(185,40))
txtSizer = wx.BoxSizer(wx.HORIZONTAL)
self.btn = wx.Button(self.panel,id=wx.ID_ANY,label="Submit",pos=
(190,70),size=(100,30))
self.btn.Bind(wx.EVT_BUTTON,self.onSubmit)
def onSubmit(self,event):
gettxt = self.txt.GetValue()
I got the solution
def onBtn(self,event):
self.val = self.txtstring1.GetValue()
Blue = wx.Button(self,label="Blue",pos=(30,50))
Blue.Bind(wx.EVT_BUTTON,self.onBlue)
Green = wx.Button(self,label="Green",pos=(300,50))
Green.Bind(wx.EVT_BUTTON,self.onGreen)
for self.button_name in range(self.val):
self.btn = wx.Button(self, label=str(self.button_name),pos=(50,50))
self.btn.Bind(wx.EVT_BUTTON, lambda evt, temp=self.button_name:
self.OnButton(evt, temp))
self.widgetSizer.Add(self.btn, 0, wx.ALL|wx.CENTER, 5)
I am programming an application using wxpython and wx.lib.pubsub. in python 2.7.3
1- There is a Frame with a menu item. When this menu is clicked, a message is published by pubsub.
2- This message destroys (if possible) and creates a "first level" dialogue.
3- "First Level" dialogue has an list of valules and an "add value" button. (NOTE: Such list of variables can be modified so I am trying to update this list)
4- When the "add value" button is clicked, another message is published by pubsub.
5- This message creates a "Second Level" dialogue, so a new name for the new variable can be written.
6- There is a "continue" button in this "second level" dialogue which has two consequences:
First one: Self.Destroy();
Second one: goes to step 2, i.e. destroys the "first level" dialogue and creates it again.
To that point the program seems to work fine, however, when I finish "adding" variables to the "first level" dialogue I Destroy it and then I cannot go back to the main Frame stated in step 1.
Why is this happening?
All the Dialogues are shown via ShowModal(). However if I use only Show() it seems to work fine but, since the program has many menus and items, ShowModal() is preferred.
Any idea why it works with Show() but not with ShowModal()?
If there is a simpler way to perform the task I want to do, it would be appreciated.
import wx
from wx.lib.pubsub import Publisher as pub
class itemReceiver(object):
def __init__(self):
pub.subscribe(self.__OnShowDialog, 'show.dialog')
def __OnShowDialog(self, message):
self.dlgParent = message.data[0]
print str(self.dlgParent)
self.valuesToShow = message.data[1]
print self.valuesToShow
#try to destroy dialog before creating a new one
try:
self.manageParametersDialog.Destroy()
except:
pass
self.manageParametersDialog = manageParamsDialog(self.dlgParent, self.valuesToShow)
print "ready to show first level dialogue"
self.manageParametersDialog.ShowModal() #if .Show() instead, there is no problem
class secondaryReceiver(object):
def __init__(self):
pub.subscribe(self.__OnShowDialog, 'add.item')
def __OnShowDialog(self, message):
dlgParent = message.data[0]
dlgGrandParent = message.data[1]
self.variableList = message.data[2]
editParameterDialog = editParamDlg(dlgParent, dlgGrandParent, self.variableList)
editParameterDialog.ShowModal()
class manageParamsDialog (wx.Dialog):
def __init__(self, parent, valueList):
self.valueList = valueList
self.parent = parent
wx.Dialog.__init__(self, parent, -1, "first level dialogue", style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
sizer=wx.BoxSizer(wx.VERTICAL)
self.optionList = wx.ListBox(self, -1, size=(200, 70), choices = valueList)
sizer.Add(self.optionList)
addButton = wx.Button(self, -1, 'Add New')
self.Bind(wx.EVT_BUTTON, self.OnButton, addButton)
sizer.Add(addButton)
cancelButton = wx.Button(self, -1, 'Cancel')
self.Bind(wx.EVT_BUTTON, self.OnCancel, cancelButton)
sizer.Add(cancelButton)
self.SetSizer(sizer)
self.Fit()
def OnButton (self, e):
pub.sendMessage('add.item', [self, self.parent, self.valueList])
def OnCancel(self,e):
self.Destroy()
class editParamDlg(wx.Dialog):
def __init__(self, parent, grandParent, variableList):
self.variableList = variableList
self.grandParent = grandParent
wx.Dialog.__init__(self, parent, -1, "second level dialogue", style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
hboxSizer = wx.BoxSizer(wx.HORIZONTAL)
self.textInput = wx.TextCtrl(self, -1)
hboxSizer.Add(self.textInput)
addButton = wx.Button(self, -1, 'Continue')
self.Bind(wx.EVT_BUTTON, self.OnAdd, addButton)
hboxSizer.Add(addButton)
cancelButton = wx.Button(self, -1, 'Cancel')
self.Bind(wx.EVT_BUTTON, self.OnCancel, cancelButton)
hboxSizer.Add(cancelButton)
self.SetSizer(hboxSizer)
self.Fit()
def OnAdd(self, e):
self.variableList.append(self.textInput.GetValue())
self.Destroy()
pub.sendMessage('show.dialog',[self.grandParent, self.variableList])
def OnCancel(self,e):
self.Destroy()
class ToolbarFrame(wx.Frame):
#this ToolbarFrame is the main window, with a Toolbar and a white panel below.
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, "this is a frame", size=(480, 320))
myPanel = wx.Panel(self)
myPanel.SetBackgroundColour("White")
menuBar = wx.MenuBar()
fileMenu = wx.Menu()
menuItem = wx.MenuItem(fileMenu, -1, "menu item", "opens dialog via pubsub")
self.Bind(wx.EVT_MENU, self.OnMenuItem, menuItem)
fileMenu.AppendItem(menuItem)
menuBar.Append(fileMenu, "File")
self.SetMenuBar(menuBar)
def OnMenuItem(self, e):
pub.sendMessage('show.dialog', [self, ["one", "two", "three"]])
app = wx.PySimpleApp()
frame = ToolbarFrame(parent=None, id=-1)
frame.Show()
newItemListener = itemReceiver()
editParameterListener = secondaryReceiver()
app.MainLoop()
try changing secondaryReciever as follows
class secondaryReceiver(object):
def __init__(self):
pub.subscribe(self.__OnShowDialog, 'add.item')
def __OnShowDialog(self, message):
dlgParent = message.data[0]
dlgGrandParent = message.data[1]
self.variableList = message.data[2]
editParameterDialog = editParamDlg(dlgParent, dlgGrandParent, self.variableList)
editParameterDialog.ShowModal()
#this line will not execute till the dialog closes
self.dlgParent.optionList.SetItems(editParameterDialog.variableList)
editParameterDialog.Destroy()
and also change editParamDlg
def OnAdd(self, e):
self.variableList.append(self.textInput.GetValue())
self.Close()
the problem was that you would call the show.modal from that OnAdd ... which would try to destroy the existing window and then open a new one... but the old one wasnt destroyed ... this left weird remnants that caused you errors ... and really all you want to do is update the item list ...
I am using Python WX to make a large GUI containing maybe 100 CheckBoxes. I want to read the value of each checkbox and append these values to a list. I can do this with 100 lines of code but prefer to use a loop. In the loop, how can I identify or select the specific checkbox I want to get the value from?
self.Box1 = wx.CheckBox(self.panel, id = 1, label='first box', pos=(10, 25), size=(30,22))
self.Box2 = wx.CheckBox(self.panel, id = 2, label='second box', pos=(20, 25), size=(30,22))
.
.
.
self.Box100 = wx.CheckBox(self.panel, id = 100, label='100th box', pos=(100, 25), size=(30,22))
Looking for something like:
MyList = []
for N in range (1, 101):
MyList.append(self.Box + N.Value)
The more generic question here is "how to select an object name in a loop"
I have searched all day with no luck. I am not a programming expert and hope this is worthy of someone's answer.
Rather than having 100 almost-identical lines of code, which is error-prone, inefficient and unattractive, actually build the CheckBoxes in a loop and hold them in a list:
self.boxes = []
for i in range(1, 101):
self.boxes.append(wx.CheckBox(self.panel, id=i,
label="Box {0}".format(i)
pos=(10, 25), size=(30,22)))
Then getting all of the values is similarly simple:
for i, box in enumerate(self.boxes, 1):
...
as is accessing a single one:
box = self.boxes[i-1]
If you really want "first", "second", "100th" write a helper function to process i into a string representation.
I personally like to use widget names. For example:
import wx
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
self.sizer = wx.BoxSizer(wx.VERTICAL)
for i in range(5):
txt = "Checkbox #%s" % i
chk = wx.CheckBox(self, label=txt, name=txt)
self.sizer.Add(chk, 0, wx.ALL|wx.CENTER, 5)
button = wx.Button(self, label="Get check")
button.Bind(wx.EVT_BUTTON, self.onButton)
self.sizer.Add(button, 0, wx.ALL|wx.CENTER, 5)
self.SetSizer(self.sizer)
#----------------------------------------------------------------------
def onButton(self, event):
""""""
widget = self.FindWindowByName("Checkbox #0")
print widget
print widget.GetValue()
########################################################################
class MyFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="Checkboxes")
panel = MyPanel(self)
self.Show()
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.App(False)
frame = MyFrame()
app.MainLoop()
This code will create a set of 5 wx.Checkboxes that each have a unique name. Then you can look them up by name using wx.FindWindowByName.
You could also create a dictionary using the names as the keys and the values as the CheckBox widgets which gives the advantage of being a faster lookup.
I'm working on a program that is going to be used with a Time Motion study. There are times that the user may have to create add new objects (Observer, Subject, Clinic). In order to accomplish this I have employed the use of a modal dialog box, (since all data is associated to a subject, observer, and clinic).
I have created a general class for the dialog boxes, and then just create an instance of this class for each dialog box. However, when the user creates a new entry with one class, and then the other, the previous classes input is created again, thus causing a duplicate in data.
I'm not exactly sure what's going on and looking for some help:
Here's my general dialog box class:
class NewDataDialog(wx.Dialog):
def __init__(self, parent, id, title, databoxes, pubsubmessage):
wx.Dialog.__init__(self,parent,id, title)
self.databoxes = databoxes
self.pubsubmessage = pubsubmessage
# MainSizer Creation
self.MainSizer = wx.BoxSizer(wx.VERTICAL)
# Top Label Creation and addition to Main Sizer
self.TopLbl = wx.StaticText(self, -1, "Create a " + title)
self.TopLbl.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD))
self.MainSizer.Add(self.TopLbl, 0, wx.ALL|wx.ALIGN_CENTER, 5)
self.SubSizer = wx.BoxSizer(wx.HORIZONTAL)
# Labels
self.LblSizer = wx.BoxSizer(wx.VERTICAL)
for lbl in databoxes:
self.lbl = wx.StaticText(self, -1, lbl+":")
self.LblSizer.Add(self.lbl, 0, wx.ALL|wx.ALIGN_LEFT, 5)
self.SubSizer.Add(self.LblSizer, 0, wx.ALL|wx.ALIGN_LEFT, 5)
# Boxes
self.InputSizer = wx.BoxSizer(wx.VERTICAL)
for lbl in databoxes:
self.box = wx.TextCtrl(self, -1, style=wx.ALIGN_LEFT)
self.InputSizer.Add(self.box, 0, wx.ALL, 1)
self.SubSizer.Add(self.InputSizer, 0, wx.ALL|wx.ALIGN_LEFT, 5)
self.MainSizer.Add(self.SubSizer, 0, wx.ALL|wx.ALIGN_CENTER, 5)
# Save and Cancel Buttons
self.buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
self.saveButton = SaveButton(self, 'Save')
self.cancelButton = CancelButton(self, 'Cancel')
self.buttonSizer.Add(self.saveButton, 0, wx.ALL|wx.ALIGN_CENTER, 5)
self.buttonSizer.Add(self.cancelButton, 0, wx.ALL|wx.ALIGN_CENTER, 5)
self.MainSizer.Add(self.buttonSizer, 0, wx.ALL|wx.ALIGN_CENTER, 5)
self.SetSizerAndFit(self.MainSizer)
pub.subscribe(self.cancelbutton, "mainpanel.CancelButton")
pub.subscribe(self.savebutton, "mainpanel.SaveButton")
def cancelbutton(self, message):
self.Close()
def savebutton(self, message):
results = []
for lbl in self.databoxes:
results.append(self.box.GetValue())
pub.sendMessage(self.pubsubmessage, results)
self.Close()
class CancelButton(wx.Panel):
def __init__(self, parent, title):
wx.Panel.__init__(self, parent)
self.dialogbutton = wx.Button(self, -1, title)
self.Bind(wx.EVT_BUTTON, self.OnButtonActivate, self.dialogbutton)
def OnButtonActivate(self, event):
pub.sendMessage("mainpanel.CancelButton", "")
class SaveButton(CancelButton):
def OnButtonActivate(self, event):
pub.sendMessage("mainpanel.SaveButton", "")
And here's the creation of each instance of the dialog box:
def newsubject(self, message):
titles = ["Full Name", "Initials", "Job Title"]
self.newsubject = NewDataDialog(self, 0, 'New Subject', titles, "MainPanel.NewSubjectDialog.Save")
self.newsubject.ShowModal()
def newobserver(self, message):
titles = ["Full Name", "Initials"]
self.newobserver = NewDataDialog(self, 1, 'New Observer', titles, "MainPanel.NewObserverDialog.Save")
self.newobserver.ShowModal()
def newclinic(self, message):
titles = ["Clinic Name","Location","Initials"]
self.newclinic = NewDataDialog(self, 2, 'New Clinic', titles, "MainPanel.NewClinicDialog.Save")
self.newclinic.ShowModal()
Where each of these are called if the user selects a button labeled for the action that they desire. I.e. "Create a New Observer" will run the function newobserver
For a full view of the code you can look here. Note: Not all comments are correctly annotated, and there are other files as a part of this and so therefore won't run, but will hopefully give you a little more insight to what's going on
You are storing references to the NewDataDialog instances in self.newsubject, self.newobserver and self.newclinic. This means the objects continue to exist, and to listen for "mainpanel.SaveButton" events, even after the newsubject, newobserver, and newclinic methods exit. Once you've opened one of each kind of dialog box, there will always be three such objects hanging around, and each "mainpanel.SaveButton" event will cause all three to try and save their data.
If you did not store these references, then the objects would apparently be garbage collected, and the subscriptions automatically removed. If you do need to store the references, then you should arrange for an unsubscribe to happen after the ShowModal().
def cancelbutton(self, message):
pub.unsubscribe(self.savebutton, "mainpanel.SaveButton")
pub.unsubscribe(self.cancelbutton, "mainpanel.CancelButton")
self.Close()
def savebutton(self, message):
results = []
for lbl in self.databoxes:
results.append(self.box.GetValue())
pub.sendMessage(self.pubsubmessage, results)
pub.unsubscribe(self.savebutton, "mainpanel.SaveButton")
pub.unsubscribe(self.cancelbutton, "mainpanel.CancelButton")
self.Close()