[Tutor] critique my script!
Danny Yoo
dyoo at hkn.eecs.berkeley.edu
Wed Jun 21 04:10:30 CEST 2006
On Tue, 20 Jun 2006, Christopher Spears wrote:
> Here is a little gui I created:
[gui code cut]
Hi Christopher,
Looks ok so far.
One approach that has a lot of popularity behind it is called the
"model-view-controller" approach. The idea is that we should be able to
build up the graphical part, the part that does all the windows and
buttons and textboxes. We should be able to develop this "view"
independently of the part that does the real work, the model. We should
then be able to control these two parts and explicitely link them
together.
Concretely, we can take the program you showed us, and make it temporarily
less useful. *grin*
Here's an example of this:
##################################################################
class View:
def __init__(self):
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_title("Get Current Working Dir")
self.window.set_border_width(10)
self.window.connect("delete_event", self.delete_event)
self.box = gtk.HBox(False, 0)
self.window.add(self.box)
self.button = gtk.Button("Current Working Directory")
self.button.connect("clicked", self.button_pressed)
self.box.pack_start(self.button, True, True, 0)
def do_nothing():
pass
self.on_button_pressed = do_nothing
self.button.show()
self.box.show()
self.window.show()
def button_pressed(self, widget, data=None):
self.on_button_pressed()
def delete_event(self, widget, event, data=None):
gtk.main_quit()
return False
def main(self):
gtk.main()
##################################################################
It's basically your program, minus any of the useful stuff that does
getcwd(). There's a small level of indirection here: the button is hooked
up to button_pressed, which calls on_button_pressed, which does_nothing.
And of course, this is useless! We can bring up this view, and press its
buttons, but nothing happens.
However, we can fix that: we can rewire up the view so that
on_button_pressed doesn't do_nothing(), but does something more
interesting, something like:
#########################################
view = View()
view.on_button_pressed = os.getcwd
#########################################
If we do then, then we can patch up our main entry point and get back the
original behavior of the program:
######################################
if __name__ == '__main__':
view = View()
view.on_button_pressed = os.getcwd
view.main()
######################################
But why bother with this?
The advantage of this approach is that it becomes easy to rewire this same
view with different models. For example:
######
view = View()
def say_hello():
print "hello world"
view.on_button_pressed = say_hello
######
Bam. Now we have a GUI that should say hello when we press the button.
Of course, the title bars and button text are all wrong. But that's
something that can be fixed by making the View more general and passing in
the explicit text strings into the constructor.
###############################################################
class OneButtonView:
def __init__(self, title, button_text):
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_title(title)
self.window.set_border_width(10)
self.window.connect("delete_event", self.delete_event)
self.box = gtk.HBox(False, 0)
self.window.add(self.box)
self.button = gtk.Button(button_text)
self.button.connect("clicked", self.button_pressed)
self.box.pack_start(self.button, True, True, 0)
def do_nothing():
pass
self.on_button_pressed = do_nothing
self.button.show()
self.box.show()
self.window.show()
def button_pressed(self, widget, data=None):
self.on_button_pressed()
def delete_event(self, widget, event, data=None):
gtk.main_quit()
return False
def main(self):
gtk.main()
##############################################################
And now we can either have the original program:
###############################################################
def cwd_gui_program():
view = OneButtonView("Get Current Working Directory",
"Current Working Directory")
view.on_button_pressed = os.getcwd
view.main()
###############################################################
Or we can have a happy hello world gui:
###############################################################
def hello_world_gui_program():
view = OneButtonView("Hello World", "Press me please")
def say_hello():
print "hello happy world"
view.on_button_pressed = say_hello
view.main()
###############################################################
The point is that if we break things up like this, we now have a general
OneButtonView GUI that shows up a button, and lets the user press it to
activate a function.
Does this make sense?
Best of wishes!
More information about the Tutor
mailing list