Google Analytics

Monday, May 12, 2014

Learning Kivy - Part 6

Prev

Table of Contents



  • Learning Kivy - Part 1
  • Learning Kivy - Part 2
  • Learning Kivy - Part 3
  • Learning Kivy - Part 4
  • Learning Kivy - Part 5
  • Learning Kivy - Part 6



  • After a LOT OF WORK, I was finally able to get some code working that incorporates the following:


    • Thread, with a simulation of a Socket.  This writes to a Queue.
    • Main thread - Kivy GUI thread, that reads from the Queue
    • Queues
    Where I've been having issues is:
    • Getting both threads up and running (Thread for Socket simulation, thread for main Kivy GUI), while not causing either thread to block.  Over the years, I've written a lot of Thread software, yet there still issues.  I still don't know what the problem was.
    • Getting both threads to use the same Queue.  For some brain-fart reason, I was creating two (2) Queues, one in each thread, then was surprised that the data I was pushing into the Queue wasn't available to be read on the other Queue!  Clearly a misunderstanding on my part.  I've used Queues before, and knew how they worked, so I don't even have the excuse of ignorance to justify this - it was just a plain brain-fart.  In the code, I create a global variable that has the Queue, which makes it available for each thread.  I'm not saying that's the best approach, but I wasn't trying to research the best approach for Queues, I was trying to get Kivy going.
    • These were the two (2) main problems.

    Here's the code.  It does the following:
    1. Builds a simple Kivy Language BoxLayout (via my ShowGUI class) via the 'Bulder.load_string' command.
    2. Creates a global variable q and assigns Queue instance to it.
    3. Creates an instance of my SimSocket class.  The class has methods that will create some data, then push it onto the Queue.
    4. Creates a Thread named 'simSocket' that links to the callback SimSocket method "put_on_queue".
    5. Starts the 'simSocket' thread.
    6. Runs Kivy.
    Once running, the following takes place:
    1. On the Terminal, initialization messages, followed by comments that say data is being written to the Queue, and shows the data.
    2. A pop-up GUI appears.
    3. Data is read from the queue.
    4. The GUI updates with the  the data that is being pulled from the queue, at a rate of 1/60 of a second.
    5. It continues to run until you stop it, or it reaches 1 million messages.
    ======Python Code Follows=========

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #
    #  threads_and_kivy.py
    #  
    '''threads_and_kivy.py
    Trying to build up a foundation that satisfies the following:
        - has a thread that will implement code that:
            - simulates reads data from a Python socket
            - works on the data
            - puts the data onto a Python Queue
        - has a Kivy mainthread that:
            - via class ShowGUI
                - reads data from the Queue
                - updates a class variable of type StringProperty so it will
                    update the label_text property.
              
    '''

    from threading import Thread
    from Queue import Queue, Empty
    import time


    from kivy.app import App
    from kivy.uix.boxlayout import BoxLayout
    from kivy.properties import StringProperty
    from kivy.lang import Builder
    from kivy.clock import Clock


    kv='''

    :
        Label:
            text: str(root.label_text)
    '''

    Builder.load_string(kv)

    q = Queue()    

            
    class SimSocket():
        global q

        def __init__(self, queue):
            self.q = queue

        def put_on_queue(self):
            print("<----- ..threaded..simsocket.put_on_queue="" entry="" font="">
            for cntr in range(1000000):
                print(".....threaded.....SimSocket.put_on_queue(): Loop " + str(cntr))
                self.some_data = ["SimSocket.put_on_queue(): Data Loop: cntr: " + str(cntr)]
                self.q.put(self.some_data)
            print("..threaded..SimSocket.put_on_queue(): thread ends")

    class ShowGUI(BoxLayout):
        label_text = StringProperty("Initial - not data")
        global q
        
        def __init__(self):
            super(ShowGUI, self).__init__()
            print("ShowGUI.__init__() entry")
            Clock.schedule_interval(self.get_from_queue, 1.0 / 60.0)

        def get_from_queue(self, dt):
            print("---------> ShowGUI.get_from_queue() entry")
            try:
                queue_data = q.get(timeout = 5)
                self.label_text = queue_data[0]
                for qd in queue_data:
                    print("SimKivy.get_from_queue(): got data from queue: " + qd)
            except Empty:
                print("Error - no data received on queue.")
                print("Unschedule Clock's schedule")
                Clock.unschedule(self.get_from_queue)
        
        
    class KivyGui(App):
        def build(self):
            return ShowGUI()
        

    def main():

        global q
        ss = SimSocket(q)
        
        simSocket_thread = Thread(name="simSocket",target=ss.put_on_queue)
        simSocket_thread.start()
        
        
        print("Starting KivyGui().run()")

        KivyGui().run()
        
        
        return 0

    if __name__ == '__main__':

        main()



    BBQ Review - Hickory Pit Bar-B-Queue, Chattanooga, Tennessee

    BBQ Review - Hickory Pit Bar-B-Queue, Chattanooga, Tennessee

    Note: I don't publish any negative reviews at all, so you only see reviews for places I stop at and enjoy.  I don't think it's fair to write a negative review for an establishment that might have had an off day.

    These guys (Mr. and Mrs. Ford) just won Fifth in a Nation-wide award from TripAdvisor!  That's no small feat; per TripAdvisor, their "community of millions of travelers" had decided that this BBQ restaurant is worthy of 5th place in the USA!

    The award was posted Thursday, May 8, 2014.  I learned of it on Friday, May 9, 2014.  I was there eating a big-ol' BBQ Pork sandwich on Saturday, May 10 - the next day!

    My wife and I planned the trip for Saturday, May 10th, 2014, to see relatives in Chattanooga TN that would require us to go right by this restaurant on our way to visit!

    Coming from Atlanta on I-75 N., we took Exit 1B for Ringgold Ave, then headed West for one (1) mile, and located the restaurant on the right side of the highway.

    It's small!  Like 2 tables outside, 4 or 5 tables inside!

    We tried to time our arrival at 11:30, so that hopefully we might avoid the major crush I was expecting.  Well, I was wrong - there was already a major crush, and it just got bigger and longer as we waited....45 minutes to be served, after waiting about 15 minutes to order.

    The staff was doing all they could, but they were overwhelmed.  Everyone was pleasant though, and we didn't hear anyone complain about the wait.

    They were, however, in addition to taking orders from the people that stood in line to place their order at the counter, also taking orders at the drive-up window, as well as orders over the phone.  That meant anyone placing an order via their car or over the phone was jumping to the head of the line and this meant the line was at least 3 times as long as what we saw standing in line. 

    At some point Mrs. Ford realized this wasn't fair to the people that had traveled to eat with them, and stopped taking any further orders over the phone, which continued to ring non-stop!

    There was no where to sit for us, so we took 'take-out', and ate it in our vehicle.  That was a little difficult, because this was a huge BBQ Pork sandwich, heavily laden with sauce!  Careful attention was required, after multiple wraps with napkins, to try and keep it off of our cloths - we both succeeded, which I would have thought would be impossible!

    So - what did we think?

    WE LIKED IT A LOT!

    Worth the wait?  No, but then nothing would have been worth the wait!  The wait will change as the excitement wears thin, or they adjust their staff to the new reality.

    WOULD WE GO BACK!  YES!  After the excitement has died down somewhat.

    This is ONE HUGE BBQ PORK SANDWICH.  Next time, I'll ask for it to be NAKED, so I can better judge the meat, but it's the real-deal!

    Friday, May 9, 2014

    BBQ in the News - Smokin' Ribs

    This is from an article on smoking ribs on a bullet-style smoker that caught my attention, and wanted to share with you.

    Link to complete article at HoddyToddy.com:


    Excerpts from the article:

    Pork Belly Slim’s Method for Mouth-Watering Barbecued Ribs

    POSTED ON 
    This photo, from D'Artagnan (dartagnan.com) shows ribs finished with coffee barbecue sauce.
    This photo, from D’Artagnan (dartagnan.com) shows ribs finished with coffee barbecue sauce (not the method used by Pork Belly Slim, but similar).










    It’s that time of year. The flowers are in bloom, the weather is warm and we’re all excited to get outside after a colder winter than we’ve had in a few years.  For me, and a lot of others, spring means BBQ season is open, and it’s time to dust off the smoker, grab some charcoal and wood for smoke, and start the fire.

    BBQ in the News - Best BBQ Restaurants

    BBQ joints travelers say are best in ratings for TripAdvisor.

    There are more restaurants in the articles, but the following are close to home


    Article From FoxNews reporting on an article from TripAdvisor:



    Wiley’s Championship BBQ, Savannah, Georgia


    TripAdvisor
    With more than 30 years of experience winning awards on the national barbecue competition scene, husband and wife team Wiley and Janet McCrary opened their first brick and mortar restaurant in 2008. The joint pleases palates with low-and-slow cooked meats including savory St. Louis cut ribs.

    Hickory Pit Bar-B-Que, Chattanooga, Tennessee


    TripAdvisor
    Amid the Ridge-and-Valley Appalachian Mountains in southeastern Tennessee, this log cabin style restaurant feeds famished barbecue fans with an emphasis on Southern hospitality. Dry-rubbed meats are smoked over hickory wood, and can be served on a plate, as a sandwich, or even stuffed inside a “killer” baked potato.

    Jim’s Smokin’ Que, Blairsville, Georgia


    TripAdvisor
    Open Thursday through Saturday, this northern Georgia smokehouse advises guest to arrive early, as their succulent meats – including ribs, brisket, pulled pork, chicken and turkey – often sell out. Those lucky enough to score a meal can also enjoy their choice of satisfying sides, from Brunswick stew to banana pudding.

    Joe’s BBQ, Blue Ridge, Georgia


    TripAdvisor
    In the midst of the Blue Ridge Mountains, this joint satisfies hungry guests with tender and moist meats complemented by a selection of sauces including “Alabama white,” a mayonnaise-based mixture that has found fame in several Southeastern states.

    Thursday, May 8, 2014

    Learning Kivy - Part 5


    Prev

    Table of Contents




  • Learning Kivy - Part 1
  • Learning Kivy - Part 2
  • Learning Kivy - Part 3
  • Learning Kivy - Part 4
  • Learning Kivy - Part 5
  • Learning Kivy - Part 6




  • This is a continuation of Learning Kivy - Part 4

    As noted in Part 4 for Pong.py and pong.kv, we've come across an important type in the Player class, of NumericProperty, the instance of which is assigned to player1 class variable.

    With respect to this program, it is an important part of being able to dynamically update the Label's text with the changing score.

    Looking at kivy.org site to get some insight into the NumericProperty, I noticed the following:

    Theses properties implement the Observer pattern. They help you to:
    • Easily manipulate widgets defined in the Kv language
    • Automatically observe any changes and dispatch functions/code accordingly
    • Check and validate values
    • Optimize memory management

    I know from previous experience what an Observer pattern is, but in essence, it allows one part of code to inform other interested parts of code that something has changed - the change is an event, and those parties that have registered their interest through a callback function, are informed of this change.  Here's a more detailed explanation from Wikipedia: Observer Pattern

    It appears that, by setting the class PongGame's attribute player1 to an instance Player, and Player is of type Widget, and Player has an attribute of score which is of type NumericProperty, we are making use of the Observer Pattern via the NumericProperty, which will(from kivy.org) "...automatically observe any changes and dispatch functions/code accordingly".  So that appears to be the magic that let's us change.

    In other words, I'm thinking it means: when we update the 'score' attribute, since it's of type NumericProperty, then it gets updated in the pong.kv class Label text, because Label text is set to "str(root.player1.score)".  Thus the new value is displayed.

    Recommended additional info
    Here's a good question/answer thread on Kivy NumericProperty.  Here's a clip from it.


    [Alexandar Taylor]: Properties hook into kivy's event system to reference each other in automatically updated ways, dispatch events when changed etc. In comparison, a normal python class level property...doesn't. Kivy properties also take care of class uniqueness, whereas class attributes are shared by all class instances which can cause you unexpected problems if they're mutable.

    For the ReferenceListProperty, this creates a property that looks like a list, but whose elements when accessed or changed automatically reference or change the component velocity_x or velocity_y. In comparison, your example of just using a tuple does none of that - if you access velocity[0] you'll probably not even get a number but instead the NumericProperty object you defined it to point at. In contrast, the ReferenceListProperty acesses and returns the velocity_x property.

    Same goes for the NumericProperty. You could create class level python attributes if you wanted (or, more usefullly, standard instance attributes created in __init__), but then you can't bind to their changes etc. with kivy's event system. Learning more about kivy will make it clear how it ties together, you generally always will be thinking in terms of properties affecting each other via the bindings that kivy properties allow.
    The guy that wrote the above, Alexander Taylor, also has a series of youtube casts.  Here's one dealing with this issue.