Using Python Tkinter on Beaglebone: Display Flicker
Question: Below is the code for displaying data on a monitor using Python and Tkinter on
BeagleBone. It works great, but the text which displays the data flickers. Any
ideas why?

    
    
    #!/usr/bin/python
    
    import alsaaudio as aa
    import audioop
    import Tkinter as tk
    import tkFont
    import threading
    import Queue
    
    started = False
    
    class Display(object):
    
        def __init__(self, parent, queue):
            self.parent = parent
            self.queue = queue
    
            self._geom = '200x200+0+0'
            parent.geometry("{0}x{1}+0+0".format(
                parent.winfo_screenwidth(), parent.winfo_screenheight()))
            parent.overrideredirect(1)
    
            parent.title('Listen')
            parent.configure(background='#000000')
            parent.displayFont = tkFont.Font(family="Unit-Bold", size=150)
            self.process_queue()
    
        def process_queue(self):
            try:
                scaled_vol = self.queue.get(0)
                self.print_message(scaled_vol)
            except Queue.Empty:
                pass
    
            self.parent.after(100, self.process_queue)
    
        def print_message(self, messageString):
            print 'message', messageString
            self.message = tk.Message(
                self.parent, text=messageString, bg="#000000",
                font=self.parent.displayFont, fg="#777777", justify="c")
            self.message.place(relx=.5, rely=.5, anchor="c")
    
    
    def setup_audio(queue, stop_event):
        data_in = aa.PCM(aa.PCM_CAPTURE, aa.PCM_NONBLOCK, 'hw:1')
        data_in.setchannels(2)
        data_in.setrate(44100)
        data_in.setformat(aa.PCM_FORMAT_S16_LE)
    
        data_in.setperiodsize(256)
    
        while not stop_event.is_set():
            # Read data from device
            l, data = data_in.read()
            if l:
                # catch frame error
                try:
                    max_vol = audioop.rms(data, 2)
                    scaled_vol = max_vol // 4680
                    print scaled_vol
    
                    if scaled_vol <= 3:
                        # Too quiet, ignore
                        continue
    
                    total_vol += scaled_vol / 10.0
    
                    if started and total_vol > 200.0:
                        started = False
                    elif started:
                        queue.put(scaled_vol)
    
                except audioop.error, e:
                    if e.message != "not a whole number of frames":
                        raise e
    
    
    def main():
        root = tk.Tk()
        queue = Queue.Queue()
        window = Display(root, queue)
    
        stop_event = threading.Event()
        audio_thread = threading.Thread(target=setup_audio,
                                        args=[queue, stop_event])
        audio_thread.start()
        try:
            root.mainloop()
        finally:
            stop_event.set()
            audio_thread.join()
            pass
    
    
    if __name__ == '__main__':
        main()
    

The monitor is 1920 x 1080. It is the only monitor I have to check it on.


Answer: For completeness the version using `configure()`:

    
    
    #!/usr/bin/python
    
    import alsaaudio as aa
    import audioop
    import Tkinter as tk
    import tkFont
    import threading
    import Queue
    
    started = False
    
    class Display(object):
    
        def __init__(self, parent, queue):
            self.parent = parent
            self.queue = queue
    
            self._geom = '200x200+0+0'
            parent.geometry("{0}x{1}+0+0".format(
                parent.winfo_screenwidth(), parent.winfo_screenheight()))
            parent.overrideredirect(1)
    
            parent.title('Listen')
            parent.configure(background='#000000')
            parent.displayFont = tkFont.Font(family="Unit-Bold", size=150)
            self.create_message()
            self.process_queue()
    
        def process_queue(self):
            try:
                scaled_vol = self.queue.get(0)
                self.message.configure(scaled_vol)
            except Queue.Empty:
                pass
    
            self.parent.after(100, self.process_queue)
    
        def create_message(self):
            self.message = tk.Message(
                self.parent, text=messageString, bg="#000000",
                font=self.parent.displayFont, fg="#777777", justify="c")
            self.message.place(relx=.5, rely=.5, anchor="c")
    
    def setup_audio(queue, stop_event):
        data_in = aa.PCM(aa.PCM_CAPTURE, aa.PCM_NONBLOCK, 'hw:1')
        data_in.setchannels(2)
        data_in.setrate(44100)
        data_in.setformat(aa.PCM_FORMAT_S16_LE)
    
        data_in.setperiodsize(256)
    
        while not stop_event.is_set():
            # Read data from device
            l, data = data_in.read()
            if l:
                # catch frame error
                try:
                    max_vol = audioop.rms(data, 2)
                    scaled_vol = max_vol // 4680
                    print scaled_vol
    
                    if scaled_vol <= 3:
                        # Too quiet, ignore
                        continue
    
                    total_vol += scaled_vol / 10.0
    
                    if started and total_vol > 200.0:
                        started = False
                    elif started:
                        queue.put(scaled_vol)
    
                except audioop.error, e:
                    if e.message != "not a whole number of frames":
                        raise e
    
    
    def main():
        root = tk.Tk()
        queue = Queue.Queue()
        window = Display(root, queue)
    
        stop_event = threading.Event()
        audio_thread = threading.Thread(target=setup_audio,
                                        args=[queue, stop_event])
        audio_thread.start()
        try:
            root.mainloop()
        finally:
            stop_event.set()
            audio_thread.join()
            pass
    
    
    if __name__ == '__main__':
        main()
    

