0
votes

I'm working on a small gui in wxPython.

One part of the program connects to a webpage to get some updates. It prints this info to a status TextCtrl.

Now, I could do this trivially in one thread, but the program will of course become unresponsive while the request to the webpage is being made. So, to get around this, I've created two additional threads that start at the beginning of the program and simply block until they get some work to do. One loads the page, and one writes to the status box.

I'm using a kind of producer/consumer style where everything is passed around with Queues.

First class:

class Loader(threading.Thread):
    def __init__(self, in_queue, msg_queue):
        threading.Thread.__init__(self)
        self.in_queue = in_queue
        self.msg_queue = msg_queue

    def run(self):
        url = self.in_queue.get()
        page = Page(url)
        self.msg_queue.put('requested page %s' % page.get_title())
        self.in_queue.task_done()

So, it waits for a url, then opens the url (Page is another custom class which just stores a couple of convenience methods for processing the returned html). Then it pushes whatever it wants to print to the TextCtrl to a msg_queue.

Second class accepts that msg_queue.

class StatusWriter(threading.Thread):
    def __init__(self, msg_queue, post_func):
        threading.Thread.__init__(self)
        self.msg_queue = msg_queue
        self.post_message = post_func

    def run(self):
        while True:
            messgae = self.msg_queue.get()
            if messgae == 'quit':
                self.msg_queue.task_done()
                break

                self.post_message(messgae)
                    self.msg_queue.task_done()

So here is where my question is. Right now, I'm not sure how to control my various wx widgets from a separate class. I've gotten around this by taking advantage of the fact that you can pass around functions, but I'm not sure if this is the correct way to go about this. It seems like it's a strange to give one tiny function from one class to another class.

The function in question is:

def post_status_update(self, msg=None):
        self.status_box.AppendText(msg)

And everything gets set up as:

self.in_queue = Queue.Queue()
self.msg_queue = Queue.Queue()

self.loader = Loader(self.in_queue, self.msg_queue)
self.status_writer = StatusWriter(
                self.in_queue, 
                self.msg_queue,
                self.post_status_update()
                )

So, my question is basically, is this an "incorrect" way to go about this? It feels like it's tightly coupling this class to a very specific part of the gui's code.

1

1 Answers

1
votes

I wouldn't necessarily call it incorrect, but there are better ways to design the interaction between the application view and underlying functionality.

You may want to look into MVP pattern (Model-View-Presenter)

http://wiki.wxpython.org/ModelViewPresenter/