class ThumbnailsCarrouselFrame(tk.Frame): def __init__(self, parent, size, *args, **kwargs): tk.Frame.__init__(self, parent, *args, **kwargs) self.parent = parent self.size = size self.fontFamily = 'System' self.config(bg='black', bd=0) self.emptyIcon = ImageTk.PhotoImage(file='resources/empty16x16.png') self.emptyThumbnail = ImageTk.PhotoImage(file='resources/empty60x60.png') self.createWidgets() self.initialize() def createWidgets(self): labelFont = tkFont.Font(family=self.fontFamily, size=9) self.thumbnailsLabels = [] self.iconsLabels = [] self.descLabels = [] for i in xrange(self.size): f = tk.Frame(self, bg='black', bd=0, padx=10) self.iconsLabels.append(tk.Label(f, bd=0, bg='white')) self.descLabels.append(tk.Label(f, bd=0, bg='white', fg='black', font=labelFont)) self.thumbnailsLabels.append(tk.Label(f, bd=0)) f.grid(row=0, column=i) def initialize(self): self.iconsTkImages = [None] * self.size self.thumbnailsTkImages = [None] * self.size self.descriptions = [None] * self.size self.rotateHandler = -1 self.workerThread = None map((lambda l: l.config(text='')), self.descLabels) def start(self, thumbnails): logging.debug('Starting carrousel of thumbnails in thread {0}...'.format(threading.current_thread().ident)) logging.debug('Carrousel of thumbnails count {0}'.format(len(thumbnails))) self.thumbnails = thumbnails self.thumbnailsIterator = ThumbnailsIterator(self.thumbnails) self.rotate() def stop(self): if self.isWorkingInBackground(): self.workerThread.join() self.after_cancel(self.rotateHandler) self.initialize() def rotate(self): if self.isWorkingInBackground(): self.workerThread.join() logging.debug('Rotating thumbnails in thread {0}...'.format(threading.current_thread().ident)) self.thumbnailsTkImages.pop(0) self.thumbnailsTkImages.append(None) self.iconsTkImages.pop(0) self.iconsTkImages.append(None) self.descriptions.pop(0) self.descriptions.append('') for i in xrange(0, self.size - 2): self.showThumbnail(i) self.workerThread = threading.Thread(target=self.displayNextThumbnail) self.workerThread.start() # For windows, to avoid using threads # self.displayNextThumbnail() def isWorkingInBackground(self): return self.workerThread is not None and self.workerThread.is_alive() def displayNextThumbnail(self): logging.debug('Displaying netxt thumbnail in thread {0}...'.format(threading.current_thread().ident)) if self.thumbnailsIterator.hasNext(): icon, description, image = self.thumbnailsIterator.next() lastIndex = self.size - 1 self.iconsTkImages[lastIndex] = ImageTk.PhotoImage(icon) if icon is not None else self.emptyIcon self.descriptions[lastIndex] = self.extractDisplayDescription(description) self.thumbnailsTkImages[lastIndex] = ImageTk.PhotoImage(image) if image is not None else self.emptyThumbnail self.showThumbnail(lastIndex) self.rotateHandler = self.after(CARROUSEL_ROTATION_DELAY, self.rotate) def extractDisplayDescription(self, description): if description is None: return '' sp = description.split('-') if len(sp) > 1: return sp[1].strip() else: return description def showThumbnail(self, i): try: iconLabel = self.iconsLabels[i] iconLabel.configure(image=self.iconsTkImages[i]) iconLabel.grid(row=0, column=0) descLabel = self.descLabels[i] descLabel.configure(text=self.descriptions[i]) descLabel.grid(row=0, column=1) thumbLabel = self.thumbnailsLabels[i] thumbLabel.configure(image=self.thumbnailsTkImages[i]) thumbLabel.grid(row=1, column=0, columnspan=2) except: pass