Updating label values using after() method . - python-2.7

I am trying to create a page in which has ten labels and then update the values using the after() method .But the screen hangs .
The start definition is bind to a button creates the labels , and then using after method i am trying to call the update method in recursive fashion to update the label values .
Is their another way to call the update() method from the main function (main) .
def update(self,i):
self.lab_hold_X=25
self.data_hold_mL_screen[i].place(x=self.lab_hold_X,y=self.y_place)
self.data_hold_mL_screen[i]['text']=str(int(self.data_hold_mL_screen[i]['text']) + 1)
self.y_place +=30
self.valuess=i+1
if self.valuess <=10:
self.after(1000,self.update(self.valuess))
else :
self.valuess=0
self.after(1000,self.update(self.valuess))
def start(self):
self.lab_hold_X=25
self.lab_hold_Y=10
for i in range(0,10):
self.lab_hold_Y +=30
self.data_hold_mL_screen[i].place(x=self.lab_hold_X,y=self.lab_hold_Y)
self.lab_hold_X =25
self.after(1000,update(0))
I basically wish to create a page wherein i can get values from any external device and then display it on the screen , screen shows 10 values , on 11th iteration a value is recieved the screen shifts upward and the 1st value is discarded and the second value is displayed in 1st label position ..

This:
self.after(1000,update(0))
... needs to be this:
self.after(1000,lambda: update(0))
The same is true for the other places you call after. after requires a reference to a function, but you are calling the function and passing the result of the function to after. And since your function returns nothing, nothing is getting executed after 1000 ms.

A simple example using a list to hold the last 10 values, and a second list to hold the Label's StringVars that are updated. And please do not use "i", "l", or "O" as single character variable names as they can look like numbers.
from Tkinter import *
from functools import partial
class LabelTest():
def __init__(self, master):
self.master=master
self.string_vars=[] ## contains pointers to the label vars
self.values=[]
self.start()
Button(self.master, text="Quit", bg="orange", width=15,
command=self.master.quit).grid(row=20)
self.update(1)
def update(self, ctr):
""" Change the StringVars to the new values
"""
if len(self.values) > 9:
## full so delete the first one
del self.values[0]
self.values.append(ctr)
## update the StringVar with the corresponding
## value from self.values
for offset in range(len(self.values)):
self.string_vars[offset].set(self.values[offset])
ctr += 1
if ctr < 20: ## let's put a limit on this
self.master.after(1000, partial(self.update, ctr))
def start(self):
""" create 10 labels with StringVars that can be changed
each time a new value is created
"""
for ctr in range(10):
var=StringVar()
lab=Label(self.master, textvariable=var).grid(row=ctr)
self.string_vars.append(var) ## the variables to be updated
## initial variable value
self.values.append("***") ## the values
master=Tk()
LabelTest(master)
master.mainloop()

Related

How do I keep dynamic Entry fields populated after the function that created them terminates?

I'm working on a GUI to automate part of my project's pipeline using Tkinter and ttk in Python 2.7. I have a main Tk() window that generates a Toplevel() window upon clicking "Auto-Detect", then creates a dynamic series of readonly Entry widgets on button click based on a list of molecular species defined elsewhere in the code.
My issue is that, while the Entry boxes do appear correctly based on the species detected, they do not stay populated with the species names once the function that created them terminates. I suspect this is because the widgets aren't global [or even within the scope of the Tk() window], but rather are defined only within the function. However, I can't create them within the block of code where the Tk() window is defined since the number of Entry boxes needed is unknown until the button is pressed (thus calling the function that creates them).
I've included an abstracted block of code below that shows the problem I'm having. Apologies if it is long. I tried to cut it down as much as possible. The comments I included in the code show my thoughts and guesses for what's going on. It should be ready to run in Python 2.7; my hope is that the only Python 3.x changes that are necessary are import modifications.
My question is, after I have dynamically created Entry widgets within a function that is called by the main Tk() window and populated them with text, how can I prevent them from depopulating when the function ends? Disclaimer: I'm not a programmer (or even in the field of computer science) by trade, so I will do my best to hang on to all technical details, but I may have to ask some dumb questions.
from Tkinter import *
import ttk
from time import sleep
def update_list(manager, rows):
species_list = ['A','B','C','D']
del rows[1:]
for widget in manager.children.values():
widget.grid_forget()
if not species_list == ['']:
species_elem_list = []
for i, each in enumerate(species_list):
## Here I attempt to create a dynamic list of StringVars to attach to the Entry fields below, based on the contents of the species list.
species_elem_list.append(StringVar())
## Here I initialize the values of the elements of the Entry fields by setting the StringVar of each.
species_elem_list[i].set(each)
## I tried to attach the value of the StringVar (from the species list) to the Entry below, but when the program is run, the Entry does not stay populated.
temp_name = ttk.Entry(manager, textvariable=species_elem_list[i], state='readonly')
temp_color = ttk.Label(manager, text='data')
temp_row = [temp_name, temp_color]
rows.append(temp_row)
for row_number in range(len(rows)):
for column_number, each in enumerate(rows[row_number]):
each.grid(column=column_number, row=row_number)
each.grid()
manager.update()
sleep(3) ## Included so that the population of the fields can be observed before they depopulate.
## After this point, the update_list function terminates.
## When that happens, the Entry fields depopulate. How can I get them to persist after the function terminates?
root = Tk()
manager = ttk.Frame(root, padding='4 5 4 4')
manager.grid(column=0, row=0, sticky=NSEW)
name_label = ttk.Label(manager, text='Name')
color_label = ttk.Label(manager, text='RGB')
rows = [[name_label, color_label]]
options = ttk.Frame(root)
options.grid(sticky=NSEW)
detect_button = ttk.Button(options, text='Auto-Detect', command=lambda: update_list(manager,rows))
done_button = ttk.Button(options, text='Done', command=root.destroy)
detect_button.grid(column=0, row=0)
done_button.grid(column=1, row=0)
root.mainloop()
Ideally, the Entry widgets will remain (and remain populated!) after the function update_list terminates. I also want to be able to interact with the contents of these widgets from outside the function.
Currently, the Entry fields populate during the course of the function update_list, then depopulate immediately once it ends. I suspect this is because the widgets and their contents are not global in scope.
In textvariable=species_elem_list you use local variable species_elem_list which stop exist when you exit update_list()
You have to create species_elem_list outside update_list() and use global species_elem_list in update_list() to use global variable instead of local one when you do species_elem_list = []
from Tkinter import *
import ttk
from time import sleep
species_elem_list = [] # <--- put here or below of update_list
def update_list(manager, rows):
global species_elem_list # <-- use global variable instead of local one
species_list = ['A','B','C','D']
del rows[1:]
for widget in manager.children.values():
widget.grid_forget()
if not species_list == ['']:
species_elem_list = []
for i, each in enumerate(species_list):
## Here I attempt to create a dynamic list of StringVars to attach to the Entry fields below, based on the contents of the species list.
species_elem_list.append(StringVar())
## Here I initialize the values of the elements of the Entry fields by setting the StringVar of each.
species_elem_list[i].set(each)
## I tried to attach the value of the StringVar (from the species list) to the Entry below, but when the program is run, the Entry does not stay populated.
temp_name = ttk.Entry(manager, textvariable=species_elem_list[i], state='readonly')
temp_color = ttk.Label(manager, text='data')
temp_row = [temp_name, temp_color]
rows.append(temp_row)
for row_number in range(len(rows)):
for column_number, each in enumerate(rows[row_number]):
each.grid(column=column_number, row=row_number)
each.grid()
manager.update()
sleep(3) ## Included so that the population of the fields can be observed before they depopulate.
## After this point, the update_list function terminates.
## When that happens, the Entry fields depopulate. How can I get them to persist after the function terminates?
root = Tk()
manager = ttk.Frame(root, padding='4 5 4 4')
manager.grid(column=0, row=0, sticky=NSEW)
name_label = ttk.Label(manager, text='Name')
color_label = ttk.Label(manager, text='RGB')
rows = [[name_label, color_label]]
options = ttk.Frame(root)
options.grid(sticky=NSEW)
detect_button = ttk.Button(options, text='Auto-Detect', command=lambda: update_list(manager,rows))
done_button = ttk.Button(options, text='Done', command=root.destroy)
detect_button.grid(column=0, row=0)
done_button.grid(column=1, row=0)
root.mainloop()

PyQt 4. I can't delete content of QLineEdit()-object

I wrote an executable example - you can test it. When you start this program you will get three QPushButton()-objects and one QLineEdit()-object. There you can install or deinstall/uninstall the event filter or close the application. Please install the event filter and type a text. You will see what I want. I want the example program to protect the space key. In this current version the user can't press the space key more than 2 times. This program does work.
But I have a little problem. When I write a text in the QLineEdit()-object and then I highlight the text and I press the delete or return key, nothing happens. I am not able to delete the text. I am also not able to copy the marked text.
Whats wrong with the code below?
#!/usr/bin/env python
import sys
from PyQt4.QtCore import QEvent, Qt
from PyQt4.QtGui import QMainWindow, QWidget, QApplication, QVBoxLayout, QLineEdit, QPushButton
class Window(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.count_space_pressed = 0
self.current_pos = None
self.init_ui()
self.init_signal_slot_push_button()
def init_ui(self):
centralwidget = QWidget(self)
self.input_line_edit = QLineEdit(self)
self.close_push = QPushButton(self)
self.close_push.setEnabled(False)
self.close_push.setText("Close")
self.push_install = QPushButton(self)
self.push_install.setText("Install eventFilter")
self.push_deinstall = QPushButton(self)
self.push_deinstall.setText("Deinstall eventFilter")
layout = QVBoxLayout(centralwidget)
layout.addWidget(self.input_line_edit)
layout.addWidget(self.push_install)
layout.addWidget(self.push_deinstall)
layout.addWidget(self.close_push)
self.setCentralWidget(centralwidget)
return
def install_filter_event(self, widget_object):
widget_object.installEventFilter(self)
return
def deinstall_filter_event(self, widget_object):
widget_object.removeEventFilter(self)
return
def init_signal_slot_push_button(self):
self.close_push.clicked.connect(self.close)
self.push_install.clicked.connect(lambda: self.install_filter_event(self.input_line_edit))
self.push_deinstall.clicked.connect(lambda: self.deinstall_filter_event(self.input_line_edit))
return
def strip_string(self, content, site=None):
if site == "right":
return content.rstrip()
elif site == "right_left":
return content.strip()
elif site == "left":
return content.lstrip()
def eventFilter(self, received_object, event):
content_line_edit = unicode(received_object.text())
if event.type() == QEvent.KeyPress:
if event.key() == Qt.Key_Space:
'''
Yes, the user did press the Space-Key. We
count how often he pressed the space key.
'''
self.count_space_pressed = self.count_space_pressed + 1
if int(self.count_space_pressed) > 1:
'''
The user did press the space key more than 1 time.
'''
self.close_push.setEnabled(False)
'''
Now we know the user did press the
space key more than 1 time. We take a look,
if variablenamed (sel.current_pos) is None.
That means, no current position is saved.
'''
if self.current_pos is None:
'''
Well no current position is saved,
that why we save the new position anf
then we set the position of the cursor.
'''
self.current_pos = received_object.cursorPosition()
received_object.setCursorPosition(int(self.current_pos))
received_object.clear()
received_object.setText(self.strip_string(content_line_edit, site="right"))
else:
'''
Well the user press the space key again, for
example 3, 4, 5, 6 times we want to keep the
old position of the cursor until he press
no space key.
'''
received_object.setCursorPosition(int(self.current_pos))
'''
We have to remove all spaces in a string
on the right side and set the content on QLineEdit-widget.
'''
received_object.clear()
received_object.setText(self.strip_string(content_line_edit, site="right"))
else: pass
else:
'''
No the user didn't press the space key.
So we set all setting on default.
'''
self.close_push.setEnabled(True)
self.current_pos = None
self.count_space_pressed = 0
received_object.clear()
received_object.setText(self.strip_string(content_line_edit, site="left"))
# Call Base Class Method to Continue Normal Event Processing
return QMainWindow.eventFilter(self, received_object, event)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
window.show()
app.exec_()
EDIT:
import sys, re
from PyQt4 import QtCore, QtGui
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.edit = QtGui.QLineEdit(self)
self.edit.textChanged.connect(self.handleTextChanged)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.edit)
# First we save the the regular expression pattern
# in a variable named regex.
## This means: one whitespace character, followed by
## one or more whitespaces chatacters
regex = r"\s\s+"
# Now we comple the pattern.
# After then we save the compiled patter
# as result in a variable named compiled_re.
self.compiled_re = re.compile(regex)
def handleTextChanged(self, text):
# When the text of a widget-object is changed,
# we do something.
# Here I am really not sure.
# Do you want to look if the given text isn't empty?
## No, we want to search the string to see if it
## contains any runs of multiple spaces
if self.compiled_re.search(text):
# We know that given text is a QString-object.
# So we have to convert the given text
# into a python-string, because we want to work
# with them in python.
text = unicode(text)
# NOTICE: Do replacements before and after cursor pos
# We save the current and correct cursor position
# of a QLineEdit()-object in the variable named pos.
pos = self.edit.cursorPosition()
# Search and Replace: Here the sub()-method
# replaces all occurrences of the RE pattern
# in string with text.
# And then it returns modified string and saves
# it in the variables prefix and suffix.
# BUT I am not sure If I understand this: [:pos]
# and [pos:]. I will try to understnand.
# I think we are talking about slicing, right?
# And I think the slicing works like string[start:end]:
# So text[:pos] means, search and replace all whitesapce
# at the end of the text-string. And the same again, but
# text[pos:] means, search and replace all whitesapce
# at the start of the string-text.
## Right, but the wrong way round. text[:pos] means from
## the start of the string up to pos (the prefix); and
## text[pos:] means from pos up to the end of the string
## (the suffix)
prefix = self.compiled_re.sub(' ', text[:pos])
suffix = self.compiled_re.sub(' ', text[pos:])
# NOTICE: Cursor might be between spaces
# Now we take a look if the variable prefix ends
# with a whitespace and we check if suffix starts
# with a whitespace.
# BUT, why we do that?
## Imagine that the string is "A |B C" (with the cursor
## shown as "|"). If "B" is deleted, we will get "A | C"
## with the cursor left between multiple spaces. But
## when the string is split into prefix and suffix,
## each part will contain only *one* space, so the
## regexp won't replace them.
if prefix.endswith(' ') and suffix.startswith(' '):
# Yes its True, so we overwrite the variable named
# suffix and slice it. suffix[1:] means, we starts
# at 1 until open end.
## This removes the extra space at the start of the
## suffix that was missed by the regexp (see above)
suffix = suffix[1:]
# Now we have to set the text of the QLineEdit()-object,
# so we put the both varialbes named prefix and suffix
# together.
self.edit.setText(prefix + suffix)
# After then, we have to set the cursor position.
# I know that the len()-method returns the length of the
# variable named prefix.
# BUT why we have to do that?
## When the text is set, it will clear the cursor. The
## prefix and suffix gives the text before and after the
## old cursor position. Removing spaces may have shifted
## the old position, so the new postion is calculated
## from the length of the current prefix
self.edit.setCursorPosition(len(prefix))
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 150, 300, 100)
window.show()
sys.exit(app.exec_())
EDIT 2:
Two question:
First Question: in the if.condition, where we take a look if prefix ends and suffix starts with sapces, there we are about to remove the extra space at the start of the suffix. But why don't we also remove the extra space at start of the prefix?
Imagine: The user types " Prefix and Suffix " - with extra whitespaces at start and end. Don't we have to remove the extra space at start of the prefix - like:
prefix= prefix[:1]?
Second Question: At the end of the handleTextChanged()-method, we have to calculate the new position of the cursor. In the current case we use prefix to get the length of the string. Why not the len from the new modified text, that is a part from prefix and suffix?
Example: The old string is " Prefix and Suffix ", the user removes the word 'and". Now our string looks like " Prefix | Suffix ". After all whitespaces are removed we get the new modified text: "Prefix Suffix". Why don't we calculate the new position from the modified text? Or did I miss something?
EDIT 3:
I am sorry, I still don't understand the situation.
First situation: When the user types the following string: "A B C |" (| it is shown as cursor). Now the user presses the space key more than 2 times, we get a prefix that contains "A B C |" - and no suffix. And currently the length of the prexis is 6 - suffix has no lenght, because its empty. And the whole word is length 6. The current position of the cursor is 7.
Second situation: The user types "A B D E F |". And now he is realizing that a letter is missing: C. He moves his cursor back between B and D and types C and then he is about to press the space key 2 times. Now we have prefix that contains "A B C " and suffix which content "D E F". The length of prefix is 6 and of suffix is 5. The length of the whole word is 11. And in this moment the current position of the cursor is 7. In this situation you take the length of prefix and set the cursor position, right?
Filtering key-presses is not enough if you really want to prevent multiple spaces.
For instance, the user can simply drag and drop multiple spaces; or paste them either with the mouse, the built-in context menu, or with the standard keyboard shortcuts.
It's also very easy to break your space-key counting method: for example, just type A B C then move back two places and delete B!
A much more robust way to do this is to connect to the textChanged signal and use a regexp to check if there's any multiple spaces. If there are, use the same regexp to replace them, and then restore the cursor to it's original position.
Here's a demo:
import sys, re
from PyQt4 import QtCore, QtGui
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.edit = QtGui.QLineEdit(self)
self.edit.textChanged.connect(self.handleTextChanged)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.edit)
self.regexp = re.compile(r'\s\s+')
def handleTextChanged(self, text):
if self.regexp.search(text):
text = unicode(text)
# do replacements before and after cursor pos
pos = self.edit.cursorPosition()
prefix = self.regexp.sub(' ', text[:pos])
suffix = self.regexp.sub(' ', text[pos:])
# cursor might be between spaces
if prefix.endswith(' ') and suffix.startswith(' '):
suffix = suffix[1:]
self.edit.setText(prefix + suffix)
self.edit.setCursorPosition(len(prefix))
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 150, 300, 100)
window.show()
sys.exit(app.exec_())
if you are using python and you have created button for removing the last character, do the following
self.PB_Back.clicked.connect(self.Keypad_Back)
def Keypad_Back(self):
self.LE_Edit.setText(self.LE_Edit.text()[:-1])
this will remove last character one at a time
to delete all the character at once, do the following
self.PB_DeleteResult.clicked.connect(self.Keypad_DeleteResult)
def Keypad_DeleteResult(self):
self.LE_Edit.setText("")

Bokeh: dashboard not updating axis range based on widget value

I am trying to implement an interactive dashboard in Bokeh with a "play" function that loops through all value pairs for two indicators selected by widgets.
Screen cap of dashboard
While the loop works, the dashboard resets the axis values for each step of the loop. So what I need is to set axis values based on the widget.value selected. To this end, I have built a data frame "ranges" that has the name of the indicator as index and the min/max value for each indicator as columns.
The updates for controls work thusly (x_axis,etc. are the names of the widgets):
controls = [x_axis, y_axis, start_yr, end_yr, years]
for control in controls:
control.on_change('value', lambda attr, old, new: update())
The update function is supposed to update the ranges upon change in the controls like this:
def update():
p.x_range = Range1d(start = ranges.loc[x_axis.value,"Min"],
end = ranges.loc[x_axis.value,"Max"])
p.y_range = Range1d(start = ranges.loc[y_axis.value,"Min"],
end = ranges.loc[y_axis.value,"Max"])
What should happen: Whenever I change the value of the widget, the ranges should update, but other than that, they should remain constant
What does happen: The ranges are set based on the value of the widget initially set and don't change on update.
I've tried to find examples trying to achieve something similar but no luck.
This is a working example:
import numpy as np
from bokeh.plotting import figure
from bokeh.models import Range1d
from bokeh.io import curdoc
x = np.linspace(0, 100, 1000)
y = np.sin(x)
p = figure(x_range=(0, 100))
p.circle(x, y)
def cb():
# this works:
p.x_range.start += 1
p.x_range.end += 1
# this also works:
#p.x_range = Range1d(p.x_range.start+1, p.x_range.end+1)
curdoc().add_periodic_callback(cb, 200)
curdoc().add_root(p)

A code needs to be continued...(Python with Tkinter)

This code is a simplified typing game, but I can't continue. The features required are:
Please don't use classes but just use FP;
When 5 random characters appear after you click the button, the 5 characters drop with a speed of 5 pixel/second, and meanwhile, you hit your keyboard to strike them. For every successful hit, your score wins by 10, and the character being hit will disappear. If not successful, they continue to drop untill the bottom edge of the canvas.
Below is part of my code, I've tried several times, but couldn't make it. How can I continue? Many thanks!
from Tkinter import *
from time import *
import string
import random
root = Tk ( )
root.title("Typing")
cvs = Canvas ( root , width=400 , height=350 , background="White" )
def Start():
s=random.sample("string.ascii_letters",5)
cvs.delete("rand")
return cvs.create_text(200,50,text=s,tags='rand',font=('Courier New',36,'normal'))
Button(root,text="Start",command=Start,width=30).pack()
cvs.pack ( )
root.mainloop ( )
You can animate an object by writing a function that draws one frame of animation, and then schedules itself to be called again in the future.
For example, to move a single object down the screen at five pixels a second you can use a function like this:
def animate(cvs, object_id):
# move down five pixels
cvs.move(object_id, 0, 5)
# call this function again in one second
# if the object is still on the screen
(x0,y0) = cvs.coords(object_id)
if y0 < cvs.winfo_height():
cvs.after(1000, animate, cvs, object_id)
You will have to modify that to handle more than one character, or call it once for each character. That decision is left up to you, this just illustrates the general technique.
Next, you can set up a binding to the <KeyPress> event, look at the character that was pressed, and if it matches something on the screen you can delete it. One simple way to keep track of what's on the screen is to map the characters to their canvas ids.
For example:
chars = {}
for char in random.sample(string.ascii_letters, 5):
obj_id = cvs.create_text(...)
chars[char] = obj_id
Now you'll have a dictionary that looks like:
{"a": 1, "X", 2, "y", 3, "f", 4, "B", 5}
You can now move or delete each canvas item by id.

Python 2.7 - Tkinter - Button to move to next item in listbox

def nextItem(self):
active = self.skill_list_listbox.get(tk.ACTIVE)
listbox_contents = self.skill_list_listbox.get(0, tk.END)
current_pos = listbox_contents.index(active)
if current_pos + 1 < len(listbox_contents):
new_pos = current_pos + 1
self.skill_list_listbox.activate(new_pos)
self.skill_list_listbox.selection_set(tk.ACTIVE)
From what I can see within documentation this should highlight and activate the next item in the listbox. If I omit the selection_set I get what I'm looking for but there's no indicator of what's active. Adding it highlights an item, but if you continue to click the "next" button it simply adds to the highlight instead of just highlighting one item creating a long section of highlighted items, which I don't want. I've tried several different methods and this has got me the closest. If there was a 'clear selection' method I suppose I could get my desired effect of just having the next item selected and highlighted, but 3 calls just to do that seems a bit much for a common task? Any thoughts, or suggestions?
Below is an example of what I think you are trying to accomplish, using a button to select the next item in a Listbox. The gist of it is in the button's callback function, which calls selection_clear then selection_set.
Updated the example, hopefully a bit clearer as to what it happening
import Tkinter
class Application(Tkinter.Frame):
def __init__(self, master):
Tkinter.Frame.__init__(self, master)
self.master.minsize(width=256, height=256)
self.master.config()
self.pack()
self.main_frame = Tkinter.Frame()
self.some_list = [
'One',
'Two',
'Three',
'Four'
]
self.some_listbox = Tkinter.Listbox(self.main_frame)
self.some_listbox.pack(fill='both', expand=True)
self.main_frame.pack(fill='both', expand=True)
# insert our items into the list box
for i, item in enumerate(self.some_list):
self.some_listbox.insert(i, item)
# add a button to select the next item
self.some_button = Tkinter.Button(
self.main_frame, text="Next", command=self.next_selection)
self.some_button.pack(side='top')
# not really necessary, just make things look nice and centered
self.main_frame.place(in_=self.master, anchor='c', relx=.5, rely=.5)
def next_selection(self):
selection_indices = self.some_listbox.curselection()
# default next selection is the beginning
next_selection = 0
# make sure at least one item is selected
if len(selection_indices) > 0:
# Get the last selection, remember they are strings for some reason
# so convert to int
last_selection = int(selection_indices[-1])
# clear current selections
self.some_listbox.selection_clear(selection_indices)
# Make sure we're not at the last item
if last_selection < self.some_listbox.size() - 1:
next_selection = last_selection + 1
self.some_listbox.activate(next_selection)
self.some_listbox.selection_set(next_selection)
root = Tkinter.Tk()
app = Application(root)
app.mainloop()