I have frames in a grid with widgets in them. These frames get destroyed and new ones are created. I want to move between these with keyboard. The Problem: every time there is a new frame it gets treated by focus next as the last one. The Question: how to focus by row instead.
def create_a_line(i):
p=1 #sometimes there are more widgets in a row, but here just take 1
bframe = Frame(root)
bframe.grid(row=i, column=0)
m = Button(bframe, text=h[i], , takefocus = 1)
m.bind('<Right>', lambda event, i=i: focus_next(i, p))
m.bind('<Double-1>', lambda event, i=i: double_click_text(i))
m.grid(row=0, column=p)
def double_click_text(i)
for widget in root.grid_slaves(row=i):
widget.destroy()
#change h[i] i.e. text of the button to something else
create_a_line(i) #with new text but same row
def focus_next(i, p): #this is what im struggling with
event.widget.tk_focusNext().focus() #this is how it is right now
#this is how i would like it to be, but no idea how:
# if in row=i other widgets with column >p: sometimes there will be more than one widget in a row
# event.widget.tk_focusNext().focus()
# else:
# set_focus(first widget in grid row=i+1)
for i in range(0, 5) #the end number is based on number of lines f.e. 5
create_a_line(i)
For lack of a better solution this is how I solved it based on comments:
labellsall=[]
h = []
def ad_to_labelsall(i, p , z):
ag = ["#"+str(i)+"i@", p, z] #made i more complicated so I dont find random numbers
labelsall.append(ag)
def del_from_labelsall(i):
agi = ("#"+str(i)+"i@")
ngip = [e for e, s in enumerate(labelsall) if agi in s]
for index in sorted(ngip, reverse=True):
del labelsall[index]
def create_a_line(i):
p=1
bframe = Frame(root)
bframe.grid(row=i, column=0)
m = Button(bframe, text=h[i], , takefocus = 1)
m.bind('<Right>', lambda event, i=i: focus_next(event, i))
m.bind('<Double-1>', lambda event, i=i: double_click_text(i))
m.grid(row=0, column=p)
ad_to_labelsall(i, p , z=m)
def double_click_text(i)
del_from_labelsall(i)
for widget in root.grid_slaves(row=i):
widget.destroy()
#some other code change h[i] i.e. text of the button to something else
create_a_line(i) #with new text but same row
def focus_next(event, i):
grid_info = event.widget.grid_info()
p = grid_info["column"]
agi = ("#"+str(i)+"i@")
ngip = [e for e, s in enumerate(labelsall) if agi in s]
for index in sorted(ngip):
the_row = labelsall[index]
if int(the_row[1]) > p: #check if other widget is in the row before jumping to next row
the_row[2].focus_set() #if other widget found focus it
return("break")
else:
pass
i_next = i+1
try:
agi_next = ("#"+str(i_next)+"i@")
ngip_next = [e for e, s in enumerate(labelsall) if agi_next in s]
labelsall[ngip_next[0]][2].focus_set()
except:
agi_next = ("#"+str(i_next+1)+"i@") #sometimes there are rows with no widgets, so just try the next one
ngip_next = [e for e, s in enumerate(labelsall) if agi_next in s]
labelsall[ngip_next[0]][2].focus_set()
return("break")