Hi I'm wxpython newbie.
and an week before I was upload my question and not yet solve.
so Today I need more help about my problem
so here is the code....
# -*- coding:utf-8 -*-
import wx
import sqlite3
from PIL import Image # for image processing
from wx.adv import Animation, AnimationCtrl # for gif Animation
conn = sqlite3.connect('reference_file.rre')
cur = conn.cursor()
class MyApp(wx.App):
def OnInit(self):
self.frame = errorCode_SAC(None, title ="Guide")
self.SetTopWindow(self.frame)
self.frame.Show()
return True
class errorCode_SAC(wx.Frame):
# constructor
def __init__(self, parent, id=wx.ID_ANY, title="Search", pos=wx.DefaultPosition, size=(1500,650), style=wx.DEFAULT_FRAME_STYLE, name=""):
super(errorCode_SAC, self).__init__(parent, id, title, pos, size, style, name="")
self.Panel_err_sac = wx.Panel(self,wx.ID_ANY, pos=(0,0), size=(774, 608))
self.Panel_dd = wx.Panel(self, wx.ID_ANY, pos=(777,0), size=(1,608))
self.Panel_err_sac_result = wx.Panel(self,wx.ID_ANY, pos=(778,0), size=(706, 308))
self.Panel_err_image = wx.Panel(self,wx.ID_ANY, pos=(778,309), size=(706,300))
self.explBox_err_sac = wx.StaticBox(self.Panel_err_sac, wx.ID_ANY, "[ Instruction ]", pos = (8,10), size=(756, 200))
self.lbname1 = wx.StaticText(self.explBox_err_sac, label="1.input name.",pos=(10,20))
self.sa_ra_code_box = wx.StaticBox(self.Panel_err_sac, wx.ID_ANY, "[ input model ]", pos=(8,230), size=(340,80))
self.sa_err_code_CeNa = wx.TextCtrl(self.sa_ra_code_box, wx.ID_ANY, pos=(8,30), size=(260,22))
self.button = wx.Button(self.sa_ra_code_box, wx.ID_OK, label="search", size=(50,23), pos = (280,30))
self.button.SetDefault()
self.sa_er_Box = wx.StaticBox(self.Panel_err_sac, wx.ID_ANY, "[ Search by input name ]", pos = (8,320), size = (340,280))
self.sa_er_inputkw = wx.StaticText(self.sa_er_Box, label="",pos=(8,15), size=(10,40), style=wx.ALIGN_LEFT)
self.sa_er_middle = wx.StaticText(self.sa_er_Box, label=" by", pos=(50,15))
self.sa_er_middle = wx.StaticText(self.sa_er_Box, label="", pos=(8,30))
self.sa_er_footer = wx.StaticText(self.sa_er_Box, label=" searched",pos=(50,30))
self.sa_er_svlist = wx.ListCtrl(self.sa_er_Box, -1, pos = (8,60), size = (330,200), style = wx.LC_REPORT | wx.SUNKEN_BORDER)
self.sa_er_svlist.InsertColumn(0,"model")
self.sa_er_svlist.InsertColumn(1,"spec")
self.sa_er_svlist.SetColumnWidth(0,100)
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.sa_err_catelist_OnClick, self.sa_er_svlist)
self.button.Bind(wx.EVT_BUTTON, self.sa_err_search_OnButton)
self.sa_er_result_Box = wx.StaticBox(self.Panel_err_sac, wx.ID_ANY, "[ check list ]", pos=(360,230), size =(405,370))
self.sa_er_question_ti = wx.StaticText(self.sa_er_result_Box, label="", pos=(50,20), size = (130,-1))
self.sa_er_question_text = wx.StaticText(self.sa_er_result_Box, label="point", pos = (10,50), size = (130,-1))
self.sa_er_question_te = wx.StaticText(self.sa_er_result_Box, label="", pos=(50,50), size = (130,-1))
self.P_err_sac_case1 = wx.StaticBox(self.Panel_err_sac_result, wx.ID_ANY, "[ check list below ]", pos = (8,10), size=(690,60))
self.P_err_sac_case2 = wx.StaticBox(self.Panel_err_sac_result, wx.ID_ANY, "[ symptom ]", pos=(8,90), size =(690,200))
self.cas2_symp = wx.StaticText(self.P_err_sac_case2, label="selected symptom is..", pos=(10,20))
self.cas2_symp_text = wx.StaticText(self.P_err_sac_case2, label="", pos=(10,40))
self.cas2_descrip = wx.StaticText(self.P_err_sac_case2, label="cause....", pos=(10,70))
self.cas2_descrip_text = wx.StaticText(self.P_err_sac_case2, label="", pos=(10,90))
# -- Combo box
items=[] # Dummy list
self.cb = wx.ComboBox(self.P_err_sac_case1, pos=(10,30),size=(500,20), choices=items, style=wx.CB_READONLY)
self.Bind(wx.EVT_COMBOBOX, self.OnSelectComboBox)
# -- search query
def sa_err_search_OnButton(self, e):
self.sa_er_inputkw.SetLabel(self.sa_err_code_CeNa.GetValue())
searchResult = "%"+self.sa_err_code_CeNa.GetValue()+"%"
self.sa_er_svlist.DeleteAllItems()
sa_err_code_CeNa = cur.execute("Select * from sa_er_cate where cate like '"+searchResult+"'")
count = 0
for i in sa_err_code_CeNa:
self.sa_er_svlist.Append(i[1:3])
count = count +1
self.sa_er_middle.SetLabel(str(count))
self.Bind(wx.EVT_CLOSE, self.on_close)
def on_close(self,e):
self.Destroy()
def sa_err_catelist_OnClick(self, event):
sa_idx = event.GetIndex()
sa_err_check = self.sa_er_svlist.GetItem(sa_idx, 0).GetText()
sa_err_check_Comment = cur.execute("select cate,chek_comment from sa_er_cate where cate ='%s'" %sa_err_check)
for row in sa_err_check_Comment:
self.sa_er_question_ti.SetLabel(row[0])
self.sa_er_question_te.SetLabel(row[1])
model_name_string = row[0]
result_query_1 = cur.execute("Select symp from sac_er_ramp where cate='%s'" % model_name_string)
list=[]
for row_test in result_query_1:
list.append(row_test[0])
self.cb.SetItems(list)
def OnSelectComboBox(self,event):
item = event.GetString()
result_query_2 = cur.execute("Select symp, descrip, judgement,image from sac_er_ramp where symp='%s'" % item)
for row in result_query_2:
self.cas2_symp_text.SetLabel(row[0])
self.cas2_descrip_text.SetLabel(row[1])
imageno = row[3]
# -- IMAGE
erim = Image.open('./image/image_error_ramp/%s.webp' % imageno)
erim.info.pop('background',None)
erim.save('./image/image_error_ramp/%s.gif' % imageno,save_all=True, loop=0)
anim = Animation('./image/image_error_ramp/%s.gif' % imageno)
ctrl = AnimationCtrl(self.Panel_err_image, -1,anim, pos=(35,40))
ctrl.Play()
os.remove('./image/image_error_ramp/%s.gif' % imageno)
if __name__=="__main__":
app = MyApp(False)
app.MainLoop()
and progress of this code is below
input "model name" at textctrl
search "relate model" and button bind to event (to get a specific model name)
select a "model" from listctrl bind to event (to get a combobox's elements)
and combobox's list fill with relate list (list's element bring from sqlie)
select a combobox element and relate image is shown (image is animated GIF)
and below is my problem
when I select combobox list and Animated GIF is played at panel.
and select combobox's another element, Animated GIF play another and image is overlap
below code...image convert and play code... i call this code "IMAGE"
(I saved all Animated GIF to webp and convert to gif that time)
erim = Image.open('./image/image_error_ramp/%s.webp' % imageno)
erim.info.pop('background',None)
erim.save('./image/image_error_ramp/%s.gif' % imageno,save_all=True, loop=0)
anim = Animation('./image/image_error_ramp/%s.gif' % imageno)
ctrl = AnimationCtrl(self.Panel_err_image, -1,anim, pos=(35,40))
ctrl.Play()
os.remove('./image/image_error_ramp/%s.gif' % imageno)
So I think maybe Solve the problem to move "IMAGE" code locate below the constructor code(because init constructor is there.)
# constructor
def __init__(self, parent, id=wx.ID_ANY, title="Search", pos=wx.DefaultPosition, size=(1500,650), style=wx.DEFAULT_FRAME_STYLE, name=""):
IMAGE CODE
and here(below the constructor code) I can't get imageno (imageno is image's name. and this name bring from sqlite, so I select a element from a combobox but I can't get any response from combobox)
and my problem is this
Can I get the image's name from the sqlite at the below of constructor code with combobox?
or otherwise at original location(below the annotation "IMAGE") any code for "Animated GIF not overlapping" ?
ps. week a go robin dunn and rolf of saxony teach me about this problem
But I can't Understand and very depressed.....
Have a Niceday
It's quite difficult to know where to start with this answer, because there are coding errors, logical errors and I do not know what the data looks like.
However, several things stand out.
sqlite queries need a fetch to return the row/rows
use fetchone(), fetchmany(n) or fetchall()
When testing print() is your friend, if not using an IDE
print the result/s to check you have what you expect
Always assume that an error could have happened, test with if or try for example
Initialise variables, especially if you are setting them in an if statement
Assume the test could fail.
That said, I applaud your go for it attitude but you could have done this in smaller steps. Master each step before attempting to put them all together.
Here is a version of your code, that comes with many caveats.
I don't know your data or data structure.
I have started by creating some dummy records in my database.
I don't know your objectives or the logic.
Only those issues I needed to address to get a basically functioning program have been addressed and I've removed some code around the image processing to help me not you.
Hopefully, you can find some benefit in the code below.
I recommend using "diff" on my code versus yours, to see what has changed.
import wx
import sqlite3
from PIL import Image # for image processing
from wx.adv import Animation, AnimationCtrl # for gif Animation
conn = sqlite3.connect('reference_file.rre', isolation_level=None)
conn.row_factory = sqlite3.Row
cur = conn.cursor()
result = cur.execute("create table if not exists sa_er_cate (cate TEXT PRIMARY KEY NOT NULL,chek_comment TEXT)");
result = cur.execute("create table if not exists sa_er_ramp (cate TEXT PRIMARY KEY NOT NULL, symp TEXT, descrip TEXT, judgement TEXT,image TEXT)");
# Define a default data
cur.execute("select * from sa_er_cate where (cate=?)",["no1"]);
MyCate = cur.fetchone()
if not MyCate:
try:
conn.execute("insert into sa_er_cate (cate, chek_comment) values (?,?)"\
,("no1","comment 1"));
except sqlite3.Error as e:
print('Default Cate Insert Error '+str(e), 'Error')
try:
conn.execute("insert into sa_er_cate (cate, chek_comment) values (?,?)"\
,("no2","comment 2"));
except sqlite3.Error as e:
print('Default Cate Insert Error '+str(e), 'Error')
cur.execute("select * from sa_er_ramp where (cate=?)",["no1"]);
MySymp = cur.fetchone()
if not MySymp:
try:
conn.execute("insert into sa_er_ramp (cate, symp, descrip, judgement, image) values (?,?,?,?,?)"\
,("no1","no1","description 1","judgement 1","Image1"));
except sqlite3.Error as e:
print('Default Symp Insert Error '+str(e), 'Error')
try:
conn.execute("insert into sa_er_ramp (cate,symp, descrip, judgement, image) values (?,?,?,?,?)"\
,("no2","no2","description 2","judgement 2","Image2"));
except sqlite3.Error as e:
print('Default Symp Insert Error '+str(e), 'Error')
class MyApp(wx.App):
def OnInit(self):
self.frame = errorCode_SAC(None, title ="Guide")
self.SetTopWindow(self.frame)
self.frame.Show()
return True
class errorCode_SAC(wx.Frame):
# constructor
def __init__(self, parent, id=wx.ID_ANY, title="Search", pos=wx.DefaultPosition, size=(1500,650), style=wx.DEFAULT_FRAME_STYLE, name=""):
super(errorCode_SAC, self).__init__(parent, id, title, pos, size, style, name="")
self.Panel_err_sac = wx.Panel(self,wx.ID_ANY, pos=(0,0), size=(774, 608))
self.Panel_dd = wx.Panel(self, wx.ID_ANY, pos=(777,0), size=(1,608))
self.Panel_err_sac_result = wx.Panel(self,wx.ID_ANY, pos=(778,0), size=(706, 308))
self.Panel_err_image = wx.Panel(self,wx.ID_ANY, pos=(778,309), size=(706,300))
self.explBox_err_sac = wx.StaticBox(self.Panel_err_sac, wx.ID_ANY, "[ Instruction ]", pos = (8,10), size=(756, 200))
self.lbname1 = wx.StaticText(self.explBox_err_sac, label="1.input name.",pos=(10,20))
self.sa_ra_code_box = wx.StaticBox(self.Panel_err_sac, wx.ID_ANY, "[ input model ]", pos=(8,230), size=(340,80))
self.sa_err_code_CeNa = wx.TextCtrl(self.sa_ra_code_box, wx.ID_ANY, pos=(8,30), size=(260,22))
self.button = wx.Button(self.sa_ra_code_box, wx.ID_OK, label="search", size=(50,23), pos = (280,30))
self.button.SetDefault()
self.sa_er_Box = wx.StaticBox(self.Panel_err_sac, wx.ID_ANY, "[ Search by input name ]", pos = (8,320), size = (340,280))
self.sa_er_inputkw = wx.StaticText(self.sa_er_Box, label="",pos=(8,15), size=(10,40), style=wx.ALIGN_LEFT)
self.sa_er_middle = wx.StaticText(self.sa_er_Box, label=" by", pos=(50,15))
self.sa_er_middle = wx.StaticText(self.sa_er_Box, label="", pos=(8,30))
self.sa_er_footer = wx.StaticText(self.sa_er_Box, label=" searched",pos=(50,30))
self.sa_er_svlist = wx.ListCtrl(self.sa_er_Box, -1, pos = (8,60), size = (330,200), style = wx.LC_REPORT | wx.SUNKEN_BORDER)
self.sa_er_svlist.InsertColumn(0,"model")
self.sa_er_svlist.InsertColumn(1,"spec")
self.sa_er_svlist.SetColumnWidth(0,100)
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.sa_err_catelist_OnClick, self.sa_er_svlist)
self.button.Bind(wx.EVT_BUTTON, self.sa_err_search_OnButton)
self.sa_er_result_Box = wx.StaticBox(self.Panel_err_sac, wx.ID_ANY, "[ check list ]", pos=(360,230), size =(405,370))
self.sa_er_question_ti = wx.StaticText(self.sa_er_result_Box, label="", pos=(50,20), size = (130,-1))
self.sa_er_question_text = wx.StaticText(self.sa_er_result_Box, label="point", pos = (10,50), size = (130,-1))
self.sa_er_question_te = wx.StaticText(self.sa_er_result_Box, label="", pos=(50,50), size = (130,-1))
self.P_err_sac_case1 = wx.StaticBox(self.Panel_err_sac_result, wx.ID_ANY, "[ check list below ]", pos = (8,10), size=(690,80))
self.P_err_sac_case2 = wx.StaticBox(self.Panel_err_sac_result, wx.ID_ANY, "[ symptom ]", pos=(8,110), size =(690,200))
self.cas2_symp = wx.StaticText(self.P_err_sac_case2, label="selected symptom is..", pos=(10,20))
self.cas2_symp_text = wx.StaticText(self.P_err_sac_case2, label="", pos=(10,40))
self.cas2_descrip = wx.StaticText(self.P_err_sac_case2, label="cause....", pos=(10,70))
self.cas2_descrip_text = wx.StaticText(self.P_err_sac_case2, label="", pos=(10,90))
# -- Combo box
items=[] # Dummy list
self.cb = wx.ComboBox(self.P_err_sac_case1, pos=(10,30),size=(500,30), choices=items, style=wx.CB_READONLY)
self.Bind(wx.EVT_COMBOBOX, self.OnSelectComboBox)
self.Bind(wx.EVT_CLOSE, self.on_close)
# -- search query
def sa_err_search_OnButton(self, e):
self.sa_er_inputkw.SetLabel(self.sa_err_code_CeNa.GetValue())
searchResult = "%"+self.sa_err_code_CeNa.GetValue()+"%"
self.sa_er_svlist.DeleteAllItems()
sa_err_code_CeNa = cur.execute("Select * from sa_er_cate where cate like '"+searchResult+"'")
rows = cur.fetchall()
count = 0
for i in rows:
self.sa_er_svlist.Append(i[0:3])
count += 1
self.sa_er_middle.SetLabel(str(count))
def on_close(self,e):
self.Destroy()
def sa_err_catelist_OnClick(self, event):
sa_idx = event.GetIndex()
sa_err_check = self.sa_er_svlist.GetItem(sa_idx, 0).GetText()
print("1",sa_err_check)
sa_err_check_Comment = cur.execute("select cate,chek_comment from sa_er_cate where cate ='%s'" %sa_err_check)
row = cur.fetchone()
print("2",row)
if row:
self.sa_er_question_ti.SetLabel(row[0])
self.sa_er_question_te.SetLabel(row[1])
print (row)
model_name_string = row[0]
result_query_1 = cur.execute("Select symp from sa_er_ramp where cate='%s'" % model_name_string)
rows = cur.fetchall()
res_list=["Select an option"]
for row_test in rows:
res_list.append(row_test[0])
self.cb.SetItems(res_list)
self.cb.SetSelection(0)
print(res_list)
self.Refresh()
def OnSelectComboBox(self,event):
item = event.GetString()
result_query_2 = cur.execute("Select symp, descrip, judgement,image from sa_er_ramp where symp='%s'" % item)
rows = cur.fetchall()
imageno = ""
for row in rows:
self.cas2_symp_text.SetLabel(row[0])
self.cas2_descrip_text.SetLabel(row[1])
imageno = row[3]
# -- IMAGE
print("Image selected:",imageno)
#erim = Image.open('./image/image_error_ramp/%s.webp' % imageno)
#erim.info.pop('background',None)
#erim.save('./image/image_error_ramp/%s.gif' % imageno,save_all=True, loop=0)
anim = Animation('./%s.gif' % imageno)
ctrl = AnimationCtrl(self.Panel_err_image, -1,anim, pos=(35,40))
ctrl.Play()
#os.remove('./image/image_error_ramp/%s.gif' % imageno)
if __name__=="__main__":
app = MyApp(False)
app.MainLoop()
Related
Probably an easy question for a Tkinter veteran but why can't I scroll in my window?
If you run this code and add multiple data ports with the button, you will see what I mean.
Can anyone modify my code to make the scroll window work please?
I am not very well versed in Tkinter yet as I am with other similar tools in other languages so I'm sure there's going to be a lot to edit here.
from tkinter import *
fields = 'Buffer Depth \n(# of max-sized packets)', 'Payload Size \n(Max=1500bytes) ', 'Duplicate Quantity'
entries =[]
root = Tk()
root.title(string= 'Buffer Testing Tool')#create window title
root.geometry('500x750')#main window dimensions
root.configure(bg= 'crimson')
canvas = Canvas(root, height = 1000)
scroll_y = Scrollbar(root, orient="vertical", command=canvas.yview)
frame = Frame()
options = ["Transmit", "Receive"]
def makeform(root, fields):#this will organize and align the labels of the entries plus the entry fields
numberCheck =0
for field in fields:
row = Frame(canvas)
if (numberCheck==0):
firstES = Label(row, text= "Data Port 1", anchor = 'center', fg = "blue")#first ES label
firstES.pack()
DPtype = Label(row, text = 'Type', width=19, anchor = 'nw')
DPtype.pack(side= LEFT)
clicked= StringVar()
clicked.set(options[0])
drop = OptionMenu(row, clicked, *options)
drop.pack(side = LEFT, padx=5, pady= 5)
numberCheck=1
row.pack(side=TOP, fill=X, padx=5, pady= 5)
entries.append((field, clicked))
rowNew= Frame(canvas)
lab = Label(rowNew, width=20, text=field, anchor = 'w')
lab.pack(side=LEFT)
ent = Entry(rowNew)
ent.pack(side=RIGHT, expand = YES, fill=X)
rowNew.pack(side=TOP, fill=X, padx=5, pady= 5)
entries.append((field, ent))
else:
lab = Label(row, width=20, text=field, anchor = 'w')
ent = Entry(row)
row.pack(side=TOP, fill=X, padx=5, pady= 5)
lab.pack(side=LEFT)
ent.pack(side=RIGHT, expand = YES, fill=X)
entries.append((field, ent))
#return entries
def addEntryField():
next_row = int(len(entries)/4)+1
numberCheck =0
for field in fields:
row = Frame(canvas)
if (numberCheck==0):
nextES = Label(row, text= ('Data Port ' +str(next_row)), anchor = 'center', fg = "blue")
nextES.pack()
DPtype = Label(row, text = 'Type', width=19, anchor = 'nw')
DPtype.pack(side= LEFT)
clicked= StringVar()
clicked.set(options[0])
drop = OptionMenu(row, clicked, *options)
drop.pack(side = LEFT, padx=5, pady= 5)
numberCheck=1
row.pack(side=TOP, fill=X, padx=5, pady= 5)
entries.append((field, clicked))
rowNew= Frame(canvas)
lab = Label(rowNew, width=20, text=field, anchor = 'w')
lab.pack(side=LEFT)
ent = Entry(rowNew)
ent.pack(side=RIGHT, expand = YES, fill=X)
rowNew.pack(side=TOP, fill=X, padx=5, pady= 5)
entries.append((field, ent))
else:
lab = Label(row, width=20, text=field, anchor = 'w')
ent = Entry(row)
row.pack(side=TOP, fill=X, padx=5, pady= 5)
lab.pack(side=LEFT)
ent.pack(side=RIGHT, expand = YES, fill=X)
entries.append((field, ent))
#return entries
if __name__=='__main__':
b1 = Button(root, text = 'Generate XML File', command=root.quit, anchor = 'center')
b1.pack(side= BOTTOM, padx=5, pady=5)
b2 = Button(root, text = 'Run TTE-Build', command=root.quit, anchor = 'center')
b2.pack(side= BOTTOM, padx=5, pady=5)
b3 = Button(root, text = 'Run TTE-Plan', command=root.quit, anchor = 'center')
b3.pack(side= BOTTOM, padx=5, pady=5)
addEntryButton = Button(root, text= 'Add Data Port', fg = "Blue", command = addEntryField)
addEntryButton.pack(side= BOTTOM, anchor = 'n', padx=5, pady= 5)
ents = makeform(root, fields)#the creation of the window happens here
root.bind('<Return>', (lambda event, e=ents: fetch(e)))#after hitting 'Enter' this will collect the entered data from the user
canvas.create_window(0, 0, anchor= 'nw', window=frame)
canvas.update_idletasks()
canvas.configure(scrollregion=canvas.bbox("all"), yscrollcommand=scroll_y.set)
canvas.pack(fill='both', expand=True, side='left')
scroll_y.pack(fill='y', side='right')
root.mainloop()
def fetch(entries):#this will print what what the entry fields are named plus what is written down in the entry fields (regardless of the # of fields)
for entry in entries:
field = entry[0]
text = entry[1].get()#collect the entry for the fields
print('%s: "%s"' % (field, text))
def Message1():
XMLdone = Label(root, text= "XML File Generated!!")
XMLdone.pack()
def Message2():
XMLdone = Label(root, text= "TTE-Plan has been completed!!")
XMLdone.pack()
def Message3():
XMLdone = Label(root, text= "TTE-Build has been completed!!")
XMLdone.pack()
#Note: The Payload Size must always be greater than or equal to 18 bytes less than the corresponding VL.
There are several problems with the code. The first is that the frame you're adding to the canvas isn't a child of the canvas, but it needs to be. You should also give this window a more descriptive name than just frame.
So, create the frame like this:
canvas = Canvas(root, height = 1000)
scroll_y = Scrollbar(root, orient="vertical", command=canvas.yview)
inner_frame = Frame(canvas)
canvas.create_window(0, 0, anchor= 'nw', window=inner_frame)
The second problem is that you're not updating the scrollregion of the canvas with the inner frame changes. This is typically done by adding a binding to the <Configure> event of the inner frame:
inner_frame.bind("<Configure>", lambda event: canvas.configure(scrollregion=canvas.bbox("all")))
The third problem is that you're adding rows to the canvas rather than to the frame. You need to make your rows children of this inner frame.
for field in fields:
row = Frame(inner_frame)
...
rowNew= Frame(inner_frame)
...
I am new to TensorFlow and I get my code running successfully by modifying tutorials from the official website.
I checked some other answers on StackOverflow, which says my problem is likely due to something is being added to the graph every time. However, I have no idea where to look for the code that might have caused this.
Also, I used tf.py_function to map the dataset because I really need to enable eagerly mode in the mapping.
def get_dataset(data_index):
# data_index is a Pandas Dataframe that contains image/label pair info, each row is one pair
data_index = prepare_data_index(data_index)
# shuffle dataframe here because dataset.shuffle is taking very long time.
data_index = data_index.sample(data_index.shape[0])
path = path_to_img_dir
# list of dataframe indices indicating rows that are going to be included in the dataset for training.
indices_ls = ['{}_L'.format(x) for x in list(data_index.index)] + ['{}_R'.format(x) for x in list(data_index.index)]
# around 310k images
image_count = len(indices_ls)
list_ds = tf.data.Dataset.from_tensor_slices(indices_ls)
# dataset.shuffle is commented out because it takes too much time
# list_ds = list_ds.shuffle(image_count, reshuffle_each_iteration=False)
val_size = int(image_count * 0.2)
train_ds = list_ds.skip(val_size)
val_ds = list_ds.take(val_size)
def get_label(index):
index = str(np.array(index).astype(str))
delim = index.split('_')
state = delim[1]
index = int(delim[0])
if state == 'R':
label = data_index.loc[index][right_labels].to_numpy().flatten()
elif state == 'L':
label = data_index.loc[index][left_labels].to_numpy().flatten()
return tf.convert_to_tensor(label , dtype=tf.float16)
def get_img(index):
index = str(np.array(index).astype(str))
delim = index.split('_')
state = delim[1]
index = int(delim[0])
file_path = '{}_{}.jpg'.format(data_index.loc[index, 'sub_folder'],
str(int(data_index.loc[index, 'img_index'])).zfill(4)
)
img = tf.io.read_file(os.path.join(path, file_path))
img = tf.image.decode_jpeg(img, channels=3)
full_width = 320
img = tf.image.resize(img, [height, full_width])
# Crop half of the image depending on the state
if state == 'R':
img = tf.image.crop_to_bounding_box(img, offset_height=0, offset_width=0, target_height=height,
target_width=int(full_width / 2))
img = tf.image.flip_left_right(img)
elif state == 'L':
img = tf.image.crop_to_bounding_box(img, offset_height=0, offset_width=int(full_width / 2), target_height=height,
target_width=int(full_width / 2))
img = tf.image.resize(img, [height, width])
img = tf.keras.preprocessing.image.array_to_img(
img.numpy(), data_format=None, scale=True, dtype=None
)
# Apply auto white balancing, output an np array
img = AWB(img)
img = tf.convert_to_tensor(img, dtype=tf.float16)
return img
def process_path(index):
label = get_label(index)
img = get_img(index)
return img, label
AUTOTUNE = tf.data.experimental.AUTOTUNE
train_ds = train_ds.map(lambda x: tf.py_function(
process_path,
[x], (tf.float16, tf.float16)), num_parallel_calls=AUTOTUNE)
val_ds = val_ds.map(lambda x: tf.py_function(
process_path,
[x], (tf.float16, tf.float16)), num_parallel_calls=AUTOTUNE)
def configure_for_performance(ds):
ds = ds.cache()
# ds = ds.shuffle(buffer_size=image_count)
ds = ds.batch(batch_size)
ds = ds.prefetch(buffer_size=AUTOTUNE)
return ds
train_ds = configure_for_performance(train_ds)
val_ds = configure_for_performance(val_ds)
return train_ds, val_ds
Can anyone please help me? Thanks!
Here is the rest of my code.
def initialize_model():
IMG_SIZE = (height, width)
preprocess_input = tf.keras.applications.vgg19.preprocess_input
IMG_SHAPE = IMG_SIZE + (3,)
base_model = tf.keras.applications.VGG19(input_shape=IMG_SHAPE,
include_top=False,
weights='imagenet')
global_average_layer = tf.keras.layers.GlobalAveragePooling2D()
prediction_layer = tf.keras.layers.Dense(class_num, activation=tf.nn.sigmoid, use_bias=True)
inputs = tf.keras.Input(shape=(height, width, 3))
x = preprocess_input(inputs)
x = base_model(x, training=True)
x = global_average_layer(x)
outputs = prediction_layer(x)
model = tf.keras.Model(inputs, outputs)
def custom_loss(y_gt, y_pred):
L1_loss_out = tf.math.abs(tf.math.subtract(y_gt, y_pred))
scaler = tf.pow(50.0, y_gt)
scaled_loss = tf.math.multiply(L1_loss_out, scaler)
scaled_loss = tf.math.reduce_mean(
scaled_loss, axis=None, keepdims=False, name=None
)
return scaled_loss
base_learning_rate = 0.001
model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=base_learning_rate, momentum=0.9),
loss=custom_loss,
metrics=['mean_absolute_error']
)
return model
def train(data_index, epoch_num, save_path):
train_dataset, validation_dataset = get_dataset(data_index)
model = initialize_model()
model.summary()
history = model.fit(train_dataset,
epochs=epoch_num,
validation_data=validation_dataset)
model.save_weights(save_path)
return model, history
Ok, so I've been tasked with creating a VERY simple GUI at work (I'm an intern). The task is to eventually connect to a machine and process real data, but right now I'm working on randomly generated sine data with noise. I've chose to work in Python 3.0, and use wxpython to create my GUI components.
As I want everything to appear on the same window, I'm using panels (hence wx.lib.plot.PlotCanvas rather than something like matplotlib.pyplot)
The problem that I have is that over time, the plot seems to 'expand' off of the panel. This is temporarily solved when I manually resize the window, but resumes again immediately after (you need to run the code to see what I mean).
Expansion over time in panel
Another problem (that has bugged me since I have started writing the code) is that sometimes when I resize the window (manually) or minimize it and then maximize it again, the timer randomly starts and stops.
I have tried all sorts of things (changing padding in sizers, extra arguments, changing time between refreshes GetBestSize()) but I believe that I simply don't understand wxpython well enough to identify where the problem is
I would really appreciate any help you can shed on either of these problems (I don't know, they might even be linked to each other).
FYI: I am not an experienced coder, and my code is not finished (I have more functions to code, but I feel like I should resolve this first). I have constructed this code by looking at different techniques from various tutorials and websites like stackoverflow, so I know it's not formatted well and could definitely be made more efficient. Also, I have removed some parts just to be safe about confidentiality - nothing important, just strings in messages.
PS: If you do have an easier way to do the whole plot/update thing that doesn't have this problem (preferably still in wx) I would be thrilled to hear that as well
And here's my code:
EDIT: Solved the expanding problem by using self.p2.SetSize((W+0,L+0)) instead of (self.p2.GetBestSize())
EDIT: Made transitions much smoother by just regenerating data and redrawing it on existing canvas in the evt_timer function (instead of recreating the whole canvas, which gave a blink-y appearance if you know what I mean)
import wx
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import leastsq
import wx.lib.plot as plot
import time
import os
wildcard = "Text File (*.txt)|*.txt|"\
"Picture (*.png)|*.png|"\
"All files (*.*)|*.*"#This wildcard shows the options for file endings in the "SAVE" tab - see OnSave(self,event)
wildcard2 = "Picture (*.png)|*.png|"\
"Text File (*.txt)|*.txt|"\
"All files (*.*)|*.*"
class PlotCanvas(plot.PlotCanvas):
def __init__(self,parent,id,size,accepted):
"""
This randomly generates sine data (with noise) and plots it to a panel.
Incorporated as a separate class instead of instatiating it as a plot.PlotCanvas object
to overcome an issue of the size of the plot in the panel.
"""
plot.PlotCanvas.__init__(self,parent,id,style=wx.BORDER_SUNKEN,size = size)
N = 100 # number of data points
self.t = np.linspace(0, 4*np.pi, N)
f = 1.15247 # Optional!! Advised not to use
self.data = 3.0*np.sin(f*self.t+0.001) + 0.5 + np.random.randn(N) # create artificial data with noise
guess_mean = np.mean(self.data)
guess_phase = 0
guess_freq = 1
guess_amp = 1
optimize_func = lambda x: x[0]*np.sin(x[1]*self.t+x[2]) + x[3] - self.data
est_amp, est_freq, est_phase, est_mean = leastsq(optimize_func, [guess_amp, guess_freq, guess_phase, guess_mean])[0]
fine_t = np.arange(0,max(self.t),0.1)
data_fit=est_amp*np.sin(est_freq*fine_t+est_phase)+est_mean
multiplier = 1
dataset1 = [(x,[d for d in self.data][[td for td in self.t].index(x)])for x in [td for td in self.t]]
fitdata1 = [(x,[df for df in data_fit][[tf for tf in fine_t].index(x)]) for x in [tf for tf in fine_t]]
dataset =[(x,y*multiplier) for (x,y) in dataset1]
fitdata = [(x,y*multiplier) for (x,y) in fitdata1]
self.data = dataset
self.data2 = fitdata
line = plot.PolyLine(self.data,legend = 'random',colour = 'light blue', width =2)
line2 = plot.PolyLine(self.data2,legend = 'sineline',colour ='black',width =2)
a = []
if "D" in accepted:
a.append(line)
if "S" in accepted:
a.append(line2)
if "G" in accepted:
pass
if "L" in accepted:
pass
gc = plot.PlotGraphics(a,'Line Graph','X','Y')
xmin = self.t[0]-0.01*(self.t[-1]-self.t[0])
xmax = self.t[-1]+0.01*(self.t[-1]-self.t[0])
self.Draw(gc,xAxis=(xmin,xmax),yAxis=(min([x[1] for x in dataset])-0.01*(max([x[1] for x in dataset])-min([x[1] for x in dataset])),
max([x[1] for x in dataset])+0.01*(max([x[1] for x in dataset])-min([x[1] for x in dataset]))))
#self.showLegend = True
#self.enableZoom = True
def Dialog(self, parent, message, c):# Will be used to notify the user of errors/processes
if c == "W":
caption = "Warning!"
dlg = wx.MessageDialog(parent, message, caption, wx.OK | wx.ICON_WARNING)
elif c == "I":
caption = "Information"
dlg = wx.MessageDialog(parent, message, caption, wx.OK | wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()#Destroys dialog on close
class Frame(wx.Frame):
"""
This is the main class. In it, we declare the separate panels, canvas, menubar, buttons and sizers.
"""
def __init__(self,parent,id,title):
wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition)
self.CurrentDirectory = os.getcwd()
self.timer=wx.Timer(self)#Instantiating the timer
self.count=0
self.Bind(wx.EVT_TIMER,self.evt_timer)#Binding it to itself so that it is always triggered
self.Bind(wx.EVT_PAINT,self.paint)
menubar = wx.MenuBar()
fileMenu = wx.Menu() #Creating the Menubar at the top
#Creating 3 menus: fileMenu,fit,and help
save = wx.Menu()
z = wx.MenuItem(save,wx.ID_ANY,'Save Raw Data\tCtrl+D')
self.Bind(wx.EVT_MENU,self.OnSave,z)
save.Append(z)
z= wx.MenuItem(save,wx.ID_ANY,'Save Image\tCtrl+I')
self.Bind(wx.EVT_MENU,self.OnSaveImage,z)
save.Append(z)
fileMenu.AppendSubMenu(save,'&Save')
fileMenu.AppendSeparator()
z = wx.MenuItem(fileMenu, wx.ID_EXIT, '&Quit\tCtrl+W')
self.Bind(wx.EVT_MENU, self.OnQuit, z)
fileMenu.Append(z)
fit = wx.Menu()#Making a check menu
self.gaussian = fit.Append(wx.ID_ANY,'Gaussian',kind = wx.ITEM_CHECK)
#self.Bind(wx.EVT_MENU,self.ToggleGaussian,self.gaussian)
fit.Check(self.gaussian.GetId(),False)
self.sine = fit.Append(wx.ID_ANY,'Sine',kind = wx.ITEM_CHECK)
#self.Bind(wx.EVT_MENU,self.ToggleSine,self.sine)
fit.Check(self.sine.GetId(),False)
self.linear = fit.Append(wx.ID_ANY,'Linear',kind=wx.ITEM_CHECK)
#self.Bind(wx.EVT_MENU,self.ToggleLinear,self.linear)
fit.Check(self.linear.GetId(),False)
help = wx.Menu()
z = wx.MenuItem(help,wx.ID_ANY,'&About\tCtrl+H')
self.Bind(wx.EVT_MENU,self.OnHelp,z)
help.Append(z)
menubar.Append(fileMenu, '&File')
menubar.Append(fit, '&Fit')
menubar.Append(help, '&Help')#adding menus to menubar
self.SetMenuBar(menubar)#formatting the frame with menubar
self.sp = wx.SplitterWindow(self)#Splitting the window into 2 panels
self.p1 = wx.Panel(self.sp,style = wx.SUNKEN_BORDER)#For buttons and user events
self.p2 = wx.Panel(self.sp,style = wx.SUNKEN_BORDER)#For display of the plot
self.sp.SplitVertically(self.p1,self.p2,300)
sizer = wx.GridBagSizer(3, 3)#Versatile sizer for layout of first panel self.p1
bitmappath = self.CurrentDirectory + "\\BITMAPS"
bmp = wx.Bitmap(bitmappath+"\\SAVE.BMP",wx.BITMAP_TYPE_BMP)
self.saveBtn = wx.BitmapButton(self.p1,wx.ID_ANY,bitmap = bmp,size =(bmp.GetWidth()+10,bmp.GetHeight()+10))
self.Bind(wx.EVT_BUTTON,self.OnSave,self.saveBtn)
sizer.Add(self.saveBtn, (0, 0), wx.DefaultSpan, wx.ALL,5)
bmp = wx.Bitmap(bitmappath +"\\START.BMP",wx.BITMAP_TYPE_BMP)
self.startBtn = wx.BitmapButton(self.p1,-1,bitmap = bmp,size =(bmp.GetWidth()+10,bmp.GetHeight()+10))# A button that starts and stops the plotting
self.startBtn.startval = "START"
self.Bind(wx.EVT_BUTTON,self.paint,self.startBtn)
sizer.Add(self.startBtn, (0, 1), wx.DefaultSpan,wx.ALL,5)
sizer1 = wx.BoxSizer(wx.VERTICAL)
W,L = self.p2.GetSize()
self.p2.canvas = PlotCanvas(self.p2,wx.ID_ANY,(W,L),["D"])
sizer1.Add(self.p2.canvas,1,wx.ALL,0,0)
self.p2.SetSizerAndFit(sizer1)
self.p1.SetSizerAndFit(sizer)
self.p2.SetSizerAndFit(sizer1)
self.p2.SetSize(W,L)
self.Maximize(True)
self.Centre()
self.Show()
############### event methods ###########
def paint(self,event):
"""
Updates the canvas based on the value of the startbtn(not the image). Bound to self.timer.
"""
bitmappath = self.CurrentDirectory + "\\BITMAPS"
if self.startBtn.startval == "START":
self.timer.Start(1)# increase the value for more time
bmp = wx.Bitmap(bitmappath + "\\STOP.BMP",wx.BITMAP_TYPE_BMP)
self.startBtn.SetBitmap(bmp)
self.startBtn.startval = "STOP"
elif self.startBtn.startval == "STOP":
self.timer.Stop()
bmp = wx.Bitmap(bitmappath+ "\\START.BMP",wx.BITMAP_TYPE_BMP)
self.startBtn.SetBitmap(bmp)
self.startBtn.startval = "START"
def evt_timer(self,event):
self.count +=1
if self.count== 10:# By increasing count (or the number in self.timer.Start()) you can increase the interval between updates
#self.p2.canvas.Clear()
sizer1 = wx.BoxSizer(wx.VERTICAL)
W,L = self.p2.GetSize()
a = ["D"]
if self.sine.IsChecked():
a.append("S")
elif self.linear.IsChecked():
a.append("L")
elif self.gaussian.IsChecked():
a.append("G")
self.p2.canvas = PlotCanvas(self.p2,wx.ID_ANY,(W,L),a)
sizer1.Add(self.p2.canvas,1,wx.ALL,0,0)
self.p2.SetSizerAndFit(sizer1)
self.p2.SetSize(self.p2.GetBestSize())
self.count=0 # reset the count
def Dialog(self, parent, message, c):# Will be used to notify the user of errors/processes
if c == "W":
caption = "Warning!"
dlg = wx.MessageDialog(parent, message, caption, wx.OK | wx.ICON_WARNING)
elif c == "I":
caption = "Information"
dlg = wx.MessageDialog(parent, message, caption, wx.OK | wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()#Destroys dialog on close
def OnSave(self,event):#Triggered by menubar and button
try:
rawdata = self.p2.canvas.data
raw_X =[x[0] for x in rawdata]
raw_Y =[x[1] for x in rawdata]
dlg = wx.FileDialog(#Code for this from http://www.blog.pythonlibrary.org
self, message="Save file as ...",
defaultDir=self.CurrentDirectory,
defaultFile=str(time.ctime()), wildcard=wildcard, style=wx.FD_SAVE
)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
dlg.Destroy()
f = open(path+".txt","w+")
for i in range(len(raw_X)):
f.write(str(raw_X[i])+"\t"+str(raw_Y[i])+"\n")
f.close()
self.Dialog(None,"File successfully saved","I")
except UnboundLocalError:#Catch error when user closes save window without selecting any directory or filename
pass
def OnSaveImage(self,event):
try:
rawdata = self.p2.canvas.data
raw_X = [x[0] for x in rawdata]
raw_Y = [x[1] for x in rawdata]
dlg = wx.FileDialog(
self, message="Save file as ...",
defaultDir=self.CurrentDirectory,
defaultFile=str(time.ctime()), wildcard=wildcard2, style=wx.FD_SAVE
)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
dlg.Destroy()
fig1 = plt.figure()
plt.plot(raw_X,raw_Y)
plt.title("Raw Data")
fig1.savefig(path+".png")
self.Dialog(None,"File successfully saved","I")
except UnboundLocalError:
pass
def OnMultiply(self,e):
try:
factor = self.x.GetValue()
factor = float(factor)
self.IntegrationTime = factor
except ValueError as e:
self.Dialog(None,str(e),"W")
def OnQuit(self, e):
self.Close()
def OnHelp(self,e):
self.Dialog(None,"N/A","I")
def ToggleSine(self,e):
pass
def ToggleLinear(self,e):
self.Dialog(None,"Not added yet","W")
def ToggleGaussian(self,e):
self.Dialog(None,"Not added yet","W")
if __name__ =="__main__":
app=wx.App()
Frame(None,-1,"N/A")
app.MainLoop()
I want to set color for words, background and foreground colors both are needed. I learned tkinter first, but it seems wxpython have no similar methods.
the following code is easy to test, copy "hello world, Hello World, heLLo WORLD" to area_example, tell me how to highlight "hello", ignorecase
#!/usr/bin/env python
# coding=utf8
import wx
rows = 5
cols = 2
vgap = 20
hgap = 10
class Search(wx.Frame):
#not_resizable = wx.DEFAULT_FRAME_STYLE ^ (wx.RESIZE_BORDER | wx.MAXIMIZE_BOX) # ok
not_resizable = wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)
def __init__(self, parent, title, size):
super(Search, self).__init__(parent, title=title, size=size, style=self.not_resizable)
self.init_elements()
self.lay_out()
self.Centre()
self.Show()
def init_elements(self):
self.panel = wx.Panel(self)
self.entry_name = wx.TextCtrl(self.panel)
self.entry_name.SetFocus()
self.btn_add = wx.Button(self.panel, label="Add")
self.btn_add.Disable()
self.btn_recite = wx.Button(self.panel, label="Recite")
self.btn_recite.Disable()
self.btn_flash = wx.Button(self.panel, label="Flash")
self.btn_flash.Disable()
self.label_phonetic = wx.StaticText(self.panel, label='')
self.area_meaning = wx.TextCtrl(self.panel, style=wx.TE_MULTILINE)
self.area_example = wx.TextCtrl(self.panel, style=wx.TE_MULTILINE)
self.btn_save = wx.Button(self.panel, label="Save")
self.btn_sort = wx.Button(self.panel, label="Sort")
def lay_out(self):
hbox = wx.BoxSizer(wx.HORIZONTAL)
grid = wx.FlexGridSizer(rows, cols, vgap, hgap)
grid.AddMany([
(self.entry_name), (self.btn_add),
(self.label_phonetic), (self.btn_recite),
(self.area_meaning, 1, wx.EXPAND), (self.btn_flash),
(self.area_example, 1, wx.EXPAND), (self.btn_sort),
(self.btn_save),
])
grid.AddGrowableCol(0, 1)
grid.AddGrowableRow(2, 1)
grid.AddGrowableRow(3, 1)
hbox.Add(grid, proportion=1, flag=wx.ALL | wx.EXPAND, border=15)
self.panel.SetSizer(hbox)
#self.panel.SetSizerAndFit(hbox)
def OnKeyUp(self, e):
code = e.GetKeyCode()
if code == wx.WXK_RETURN:
self.enter_handler(e)
def enter_handler(self, e):
word = self.entry_name.GetValue()
if word:
self.highlight(word)
def highlight(self, name):
# todo
# add background color and foreground color, ignore case
print 'highlight'
def search_test():
app = wx.App()
title = 'Search Test'
size = (800, 500)
s = Search(None, title, size)
s.entry_name.Bind(wx.EVT_KEY_UP, s.OnKeyUp)
app.MainLoop()
if __name__ == '__main__':
search_test()
the doc version when I asked the question was wxPython 3.0.3, last updated 13 March 2015 from revision 1725+2c3b7a8.
but the wxPython version brew install on osx was 3.0.2, some classes and methods were not available.
On the docs it explains how to do this: http://wxpython.org/Phoenix/docs/html/TextCtrl.html#phoenix-title-textctrl-styles
Here is an example snippet (Should go below your definition of self.area_example)
self.area_example.SetDefaultStyle(wx.TextAttr(wx.RED))
self.area_example.AppendText("Red text\n")
self.area_example.SetDefaultStyle(wx.TextAttr(wx.NullColour,
wx.LIGHT_GREY))
self.area_example.AppendText("Red on grey text\n")
self.area_example.SetDefaultStyle(wx.TextAttr(wx.BLUE))
self.area_example.AppendText("Blue on grey text\n")
As for checking if the word is "hello", I can only think right now as to bind it and check it.
self.area_example.Bind(wx.EVT_CHAR, self.OnKeyDown)
The "OnKeyDown" function is just an example. It runs but you'll most likely want a better way of doing it.
def OnKeyDown(self, e):
last_word = self.area_example.GetValue().split()[-1]
if last_word.lower() == "hello":
print("Change color")
e.Skip()
From there you should be able to accomplish what you need.
I'm trying to catch an event when the user presses COMMAND + [any other key] on OSX. Since these are actually two key presses I expect two events: One when COMMAND is pressed and one when the other key is pressed (without releasing the COMMAND key). This works fine for every modifier except COMMAND where I only get the first event. Why is that and how can I fix it?
Version: wxPython3.0-osx-cocoa-py2.7
Example code:
import wx
def OnKeyDown(e):
print "Modifiers: {} Key Code: {}".format(e.GetModifiers(), e.GetKeyCode())
app = wx.App()
frame = wx.Frame(None)
textctrl = wx.TextCtrl(frame, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.WANTS_CHARS)
textctrl.Bind(wx.EVT_KEY_DOWN, OnKeyDown)
frame.Show()
app.MainLoop()
For ALT + d the output is:
Modifiers: 1 Key Code: 307
Modifiers: 1 Key Code: 68
For SHIFT + d the output is:
Modifiers: 4 Key Code: 306
Modifiers: 4 Key Code: 68
Only for COMMAND + d the output is:
Modifiers: 2 Key Code: 308
Thanks for your help
Additional Information: I'm using OSX 10.8 on a virtual machine. As RobinDunn points out that it works on his laptop. So chances are that this is just a problem in my environment. wnnmaw provided a good workaround which works for me even on the virtual environment.
Alright, so it took me some time, but here's a working code block that does what you want.
Some Things to Note:
I did this on Windows (so there are some changes you can make such as adding support for wx.ACCEL_RAW_CTRL which corresponds to the actual control key on Mac whereas wx.ACCCEL_CTRL corresponds to the command key
This code definitely can (and needs to be) cleaned up
You'll have to add better error checking before you give this to a user
Whithout further adieu, here it is
import wx
from wx.lib.scrolledpanel import ScrolledPanel
class TestWindow(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Accelerator Table Test', size=(600, 400))
self.panel = ScrolledPanel(parent=self, id=-1)
self.panel.SetupScrolling()
#Create IDs to be used in initial acclerator table
self.functionList = [self.func1, self.func2, self.func3, self.func4, self.func5, self.OnAdd, self.OnDel]
self.functionListstr = ["self.func1", "self.func2", "self.func3", "self.func4", "self.func5", "self.OnAdd", "self.OnDel"]
self.IDDict = {i: wx.NewId() for i in range(len(self.functionList))}
self.IDDictrev = {val:key for key, val in self.IDDict.iteritems()}
self.aTableList = [(wx.ACCEL_ALT, ord('S'), self.IDDict[0]),(wx.ACCEL_CTRL, ord('Q'), self.IDDict[1])]
#Set up initial accelerator table
aTable = wx.AcceleratorTable(self.aTableList)
self.SetAcceleratorTable(aTable)
#Bind inital accelerator table IDs to functions
for i in range(len(self.functionList)):
self.Bind(wx.EVT_MENU, self.functionList[i], id=self.IDDict[i])
#Set up control widgets on GUI
self.flexgrid = wx.FlexGridSizer(cols=3, hgap=10, vgap=5)
cmdkeylbl = wx.StaticText(self.panel, -1, "Command Key")
self.cmdkey = wx.ComboBox(self.panel, style=wx.CB_READONLY)
cmdkeylist = ["Alt", "Control/Command", "Shift", "OSX Control", "None"]
self.cmdkeyconstants = {"Alt":wx.ACCEL_ALT, "Control/Command":wx.ACCEL_CTRL, "Shift":wx.ACCEL_SHIFT, "None":wx.ACCEL_NORMAL}
self.cmdkeyconstantsrev = {val:key for key, val in self.cmdkeyconstants.iteritems()}
self.cmdkey.SetItems(cmdkeylist)
hotkeylbl = wx.StaticText(self.panel, -1, "HotKey (single letter only)")
self.hotkey = wx.TextCtrl(self.panel, size=(50,-1))
funclbl = wx.StaticText(self.panel, -1, "Function")
self.func = wx.ComboBox(self.panel, style=wx.CB_READONLY)
self.func.SetItems(self.functionListstr)
self.hbox = wx.BoxSizer(wx.HORIZONTAL)
addBtn = wx.Button(self.panel, -1, "Add")
delBtn = wx.Button(self.panel, -1, "Delete")
self.Bind(wx.EVT_BUTTON, self.OnAdd, addBtn)
self.Bind(wx.EVT_BUTTON, self.OnDel, delBtn)
self.vbox = wx.BoxSizer(wx.VERTICAL)
self.curATable = wx.StaticText(self.panel, -1, self._DisplayATable())
self.flexgrid.Add(cmdkeylbl)
self.flexgrid.Add(hotkeylbl)
self.flexgrid.Add(funclbl)
self.flexgrid.Add(self.cmdkey)
self.flexgrid.Add(self.hotkey)
self.flexgrid.Add(self.func)
self.hbox.Add((20, 20), 0)
self.hbox.Add(addBtn)
self.hbox.Add((0, 0), 0)
self.hbox.Add(delBtn)
self.hbox.Add((20, 20), 0)
self.vbox.Add(self.flexgrid, flag=wx.TOP|wx.BOTTOM|wx.LEFT|wx.RIGHT|wx.EXPAND, border = 5)
self.vbox.Add(self.hbox, flag=wx.TOP|wx.BOTTOM|wx.LEFT|wx.RIGHT|wx.EXPAND, border = 5)
self.vbox.Add(self.curATable, flag=wx.TOP|wx.BOTTOM|wx.LEFT|wx.RIGHT|wx.EXPAND, border = 5)
self.panel.SetSizer(self.vbox)
self.panel.Layout()
#Class Functions
def _DisplayATable(self):
aTablelbl = ""
for cmdKey, hotKey, Func in self.aTableList:
aTablelbl += "{} + {} calls {}\n".format(self.cmdkeyconstantsrev[cmdKey], chr(hotKey), self.functionListstr[self.IDDictrev[Func]])
return aTablelbl
def OnAdd(self, event):
self.aTableList.append((self.cmdkeyconstants[self.cmdkey.GetValue()], ord(self.hotkey.GetValue()[:1].title()), self.IDDict[self.func.GetSelection()]))
print "Added {} + {} as a shortcut for {}!".format(self.cmdkey.GetValue(), self.hotkey.GetValue()[:1].title(), self.functionListstr[self.func.GetSelection()])
aTable = wx.AcceleratorTable(self.aTableList)
self.SetAcceleratorTable(aTable)
self.curATable.SetLabel(self._DisplayATable())
self.panel.Layout()
def OnDel(self, event):
if (self.cmdkeyconstants[self.cmdkey.GetValue()], ord(self.hotkey.GetValue()[:1].title()), self.IDDict[self.func.GetSelection()]) in self.aTableList:
self.aTableList.remove((self.cmdkeyconstants[self.cmdkey.GetValue()], ord(self.hotkey.GetValue()[:1].title()), self.IDDict[self.func.GetSelection()]))
aTable = wx.AcceleratorTable(self.aTableList)
self.SetAcceleratorTable(aTable)
self.curATable.SetLabel(self._DisplayATable())
self.panel.Layout()
else:
dlg = wx.MessageDialog(self, "ERROR: That combination is not in the accelerator table!", "Error", style=wx.OK)
dlg.ShowModal()
dlg.Destroy()
def func1(self, event):
dlg = wx.MessageDialog(self, "Func1", "Func1", style=wx.OK)
dlg.ShowModal()
dlg.Destroy()
def func2(self, event):
dlg = wx.MessageDialog(self, "Func2", "Func2", style=wx.OK)
dlg.ShowModal()
dlg.Destroy()
def func3(self, event):
dlg = wx.MessageDialog(self, "Func3", "Func3", style=wx.OK)
dlg.ShowModal()
dlg.Destroy()
def func4(self, event):
dlg = wx.MessageDialog(self, "Func4", "Func4", style=wx.OK)
dlg.ShowModal()
dlg.Destroy()
def func5(self, event):
dlg = wx.MessageDialog(self, "Func5", "Func5", style=wx.OK)
dlg.ShowModal()
dlg.Destroy()
app = wx.App(False)
frame = TestWindow()
frame.Show()
app.MainLoop()
Hopefully this is what you're looking for, let me know if you have any questions