Managing continuous updates

Next, we will update the position of the seek bar knob and the elapsed play duration, as shown in the following screenshot:

This is nothing but a simple form of Tkinter-based animation.

The most common pattern of animating with Tkinter involves drawing a single frame and then calling the same method using the after method of Tkinter, as follows:

def animate(self):
self.draw_frame()
self.after(500, self.animate)
Take a note of the self.after method, which calls the animate method in a loop. Once called, this function will keep updating frames once every 500 milliseconds. You can also add some conditions to break out of the animation loop. This is generally how all animations are handled in Tkinter. We will use this technique over and over again in several upcoming examples. 

Now that we know how to manage animations in Tkinter, let's use the pattern to define a method that takes care of these periodic updates.

Define a method named manage_periodic_updates_during_play, which calls itself every 1 second to update the timer and the seek bar, as follows (see code 5.07view.py):

def manage_periodic_updates_during_play(self):
self.update_clock()
self.update_seek_bar()
self.root.after(1000, self.manage_periodic_updates_during_play)

Then, define two methods named update_clock and update_seek_bar, which update the sections highlighted in the preceding screenshot.

The update_clock method gets the elapsed duration in seconds from the Player class, converts it into minutes and seconds, and updates the canvas text using canvas.itemconfig, as follows (see code 5.07view.py):

def update_clock(self):
self.elapsed_play_duration = self.player.elapsed_play_duration
minutes, seconds = get_time_in_minute_seconds(self.elapsed_play_duration)
current_time_string = '{0:02d}:{1:02d}'.format(minutes, seconds)
self.canvas.itemconfig(self.clock, text=current_time_string)

You may recall that we had previously defined a slide_to_position method in the Seekbar class. The update_seek_bar method simply calculates the proportionate position of the seek bar and then calls the slide_to_position method to slide the knob of the seekbar, as follows (see code 5.07view.py):

def update_seek_bar(self):
seek_bar_position = SEEKBAR_WIDTH *
self.player.elapsed_play_duration /self.track_length
self.seek_bar.slide_to_position(seek_bar_position)

Now, if you run 5.07view.py, add an audio file, and play it, the elapsed duration should be updated continuously in the top display. The seek bar should also move forward as the play progresses.

That's great, but there is still one small detail missing. We want that when a user clicks somewhere on the seek bar, the playing audio seeks the new position. The code for seeking a new position is simple (see code 5.07view.py):

def seek_new_position(self, event=None):
time = self.player.track_length * event.x /SEEKBAR_WIDTH
self.player.seek(time)

However, the preceding method needs to be called whenever the seek bar position is changed. Let's do this by adding a binding to the virtual event from within 5.07view.py, as follows:

self.root.bind("<<SeekbarPositionChanged>>", self.seek_new_position)

Now, when you run  5.07view.py, play an audio file and click on the seek bar; the audio should start playing from the new position.

This concludes the iteration. We will look at how to loop over tracks in the next iteration.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.186.178