<p>I have been playing with the Ruby library "shoes". Basically you can write a GUI application in the following way:</p>

<pre><code>Shoes.app do
  t = para "Not clicked!"
  button "The Label" do
    alert "You clicked the button!" # when clicked, make an alert
    t.replace "Clicked!" # ..and replace the label's text
  end
end
</code></pre>

<p>This made me think - how would I design a similarly nice-to-use GUI framework in Python? One that doesn't have the usual tyings of basically being wrappers to a C* library (In the case of GTK, Tk, wx, QT etc etc)</p>

<p>Shoes takes things from web devlopment (like <code>#f0c2f0</code> style colour notation, CSS layout techniques, like <code>:margin =&gt; 10</code>), and from ruby (extensively using blocks in sensible ways)</p>

<p>Python's lack of "rubyish blocks" makes a (metaphorically)-direct port impossible:</p>

<pre><code>def Shoeless(Shoes.app):
    self.t = para("Not clicked!")

    def on_click_func(self):
        alert("You clicked the button!")
        self.t.replace("clicked!")

    b = button("The label", click=self.on_click_func)
</code></pre>

<p>No where near as clean, and wouldn't be <em>nearly</em> as flexible, and I'm not even sure if it would be implementable.</p>

<p>Using decorators seems like an interesting way to map blocks of code to a specific action:</p>

<pre><code>class BaseControl:
    def __init__(self):
        self.func = None

    def clicked(self, func):
        self.func = func

    def __call__(self):
        if self.func is not None:
            self.func()

class Button(BaseControl):
    pass

class Label(BaseControl):
    pass

# The actual applications code (that the end-user would write)
class MyApp:
    ok = Button()
    la = Label()

    @ok.clicked
    def clickeryHappened():
        print "OK Clicked!"

if __name__ == '__main__':
    a = MyApp()
    a.ok() # trigger the clicked action
</code></pre>

<p>Basically the decorator function stores the function, then when the action occurred (say, a click) the appropriate function would be executed.</p>

<p>The scope of various stuff (say, the <code>la</code> label in the above example) could be rather complicated, but it seems doable in a fairly neat manner..</p>

[{'answer_id': 58917, 'author': 'Justin Voss', 'author_id': 5616, 'author_profile': 'https://Stackoverflow.com/users/5616', 'pm_score': 4, 'selected': True, 'text': '<p>You could actually pull this off, but it would require using metaclasses, which are <em>deep</em> magic (there be dragons). If you want an intro to metaclasses, there\'s a series of <a href="http://www.ibm.com/developerworks/linux/library/l-pymeta.html" rel="nofollow noreferrer">articles from IBM</a> which manage to introduce the ideas without melting your brain.</p>\n\n<p>The source code from an ORM like SQLObject might help, too, since it uses this same kind of declarative syntax.</p>\n'}, {'answer_id': 58990, 'author': 'dF.', 'author_id': 3002, 'author_profile': 'https://Stackoverflow.com/users/3002', 'pm_score': 2, 'selected': False, 'text': '<p>Maybe not as slick as the Ruby version, but how about something like this:</p>\n\n<pre><code>from Boots import App, Para, Button, alert\n\ndef Shoeless(App):\n    t = Para(text = \'Not Clicked\')\n    b = Button(label = \'The label\')\n\n    def on_b_clicked(self):\n        alert(\'You clicked the button!\')\n        self.t.text = \'Clicked!\'\n</code></pre>\n\n<p><a href="https://stackoverflow.com/questions/58711/how-would-you-design-a-very-pythonic-ui-framework#58917">Like Justin said</a>, to implement this you would need to use a custom metaclass on class <code>App</code>, and a bunch of properties on <code>Para</code> and <code>Button</code>. This actually wouldn\'t be too hard.</p>\n\n<p>The problem you run into next is: how do you keep track of the <em>order</em> that things appear in the class definition? In Python 2.x, there is no way to know if <code>t</code> should be above <code>b</code> or the other way around, since you receive the contents of the class definition as a python <code>dict</code>.</p>\n\n<p>However, in Python 3.0 <a href="http://www.python.org/dev/peps/pep-3115/" rel="nofollow noreferrer">metaclasses are being changed</a> in a couple of (minor) ways. One of them is the <code>__prepare__</code> method, which allows you to supply your own custom dictionary-like object to be used instead -- this means you\'ll be able to track the order in which items are defined, and position them accordingly in the window.</p>\n'}, {'answer_id': 60563, 'author': 'Toni Ruža', 'author_id': 6267, 'author_profile': 'https://Stackoverflow.com/users/6267', 'pm_score': 2, 'selected': False, 'text': "<p>This could be an oversimplification, i don't think it would be a good idea to try to make a general purpose ui library this way. On the other hand you could use this approach (metaclasses and friends) to simplify the definition of certain classes of user interfaces for an existing ui library and depending of the application that could actually save you a significant amount of time and code lines.</p>\n"}, {'answer_id': 62780, 'author': 'A Nony Mouse', 'author_id': 7182, 'author_profile': 'https://Stackoverflow.com/users/7182', 'pm_score': 2, 'selected': False, 'text': "<p>With some Metaclass magic to keep the ordering I have the following working. I'm not sure how pythonic it is but it is good fun for creating simple things. </p>\n\n<pre><code>class w(Wndw):\n  title='Hello World'\n  class txt(Txt):  # either a new class\n    text='Insert name here'\n  lbl=Lbl(text='Hello') # or an instance\n  class greet(Bbt):\n    text='Greet'\n    def click(self): #on_click method\n      self.frame.lbl.text='Hello %s.'%self.frame.txt.text\n\napp=w()\n</code></pre>\n"}, {'answer_id': 334828, 'author': 'Alcides', 'author_id': 28516, 'author_profile': 'https://Stackoverflow.com/users/28516', 'pm_score': 1, 'selected': False, 'text': '<p>I have this same problem. I wan to to create a wrapper around any GUI toolkit for Python that is easy to use, and inspired by Shoes, but needs to be a OOP approach (against ruby blocks).</p>\n\n<p>More information in: <a href="http://wiki.alcidesfonseca.com/blog/python-universal-gui-revisited" rel="nofollow noreferrer">http://wiki.alcidesfonseca.com/blog/python-universal-gui-revisited</a></p>\n\n<p>Anyone\'s welcome to join the project.</p>\n'}, {'answer_id': 334938, 'author': 'llimllib', 'author_id': 42559, 'author_profile': 'https://Stackoverflow.com/users/42559', 'pm_score': 2, 'selected': False, 'text': '<p>The only attempt to do this that I know of is <a href="http://zephyrfalcon.org/labs/dope_on_wax.html" rel="nofollow noreferrer">Hans Nowak\'s Wax</a> (which is unfortunately dead).</p>\n'}, {'answer_id': 335077, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 2, 'selected': False, 'text': '<p>The closest you can get to rubyish blocks is the with statement from pep343: </p>\n\n<p><a href="http://www.python.org/dev/peps/pep-0343/" rel="nofollow noreferrer">http://www.python.org/dev/peps/pep-0343/</a></p>\n'}, {'answer_id': 335132, 'author': 'Kris Kowal', 'author_id': 42586, 'author_profile': 'https://Stackoverflow.com/users/42586', 'pm_score': 2, 'selected': False, 'text': '<p>I was never satisfied with David Mertz\'s articles at IBM on metaclsses so I recently wrote my own <a href="http://askawizard.blogspot.com/2008/09/metaclasses-python-saga-part-4_30.html" rel="nofollow noreferrer">metaclass article</a>.  Enjoy.</p>\n'}, {'answer_id': 335358, 'author': 'liori', 'author_id': 42610, 'author_profile': 'https://Stackoverflow.com/users/42610', 'pm_score': 1, 'selected': False, 'text': "<p>If you really want to code UI, you could try to get something similar to django's ORM; sth like this to get a simple help browser:</p>\n\n<pre><code>class MyWindow(Window):\n    class VBox:\n        entry = Entry()\n        bigtext = TextView()\n\n        def on_entry_accepted(text):\n            bigtext.value = eval(text).__doc__\n</code></pre>\n\n<p>The idea would be to interpret some containers (like windows) as simple classes, some containers (like tables, v/hboxes) recognized by object names, and simple widgets as objects.</p>\n\n<p>I dont think one would have to name all containers inside a window, so some shortcuts (like old-style classes being recognized as widgets by names) would be desirable.</p>\n\n<p>About the order of elements: in MyWindow above you don't have to track this (window is conceptually a one-slot container). In other containers you can try to keep track of the order assuming that each widget constructor have access to some global widget list. This is how it is done in django (AFAIK).</p>\n\n<p>Few hacks here, few tweaks there... There are still few things to think of, but I believe it is possible... and usable, as long as you don't build complicated UIs.</p>\n\n<p>However I am pretty happy with PyGTK+Glade. UI is just kind of data for me and it should be treated as data. There's just too much parameters to tweak (like spacing in different places) and it is better to manage that using a GUI tool. Therefore I build my UI in glade, save as xml and parse using gtk.glade.XML().</p>\n"}, {'answer_id': 335400, 'author': 'muhuk', 'author_id': 42188, 'author_profile': 'https://Stackoverflow.com/users/42188', 'pm_score': 0, 'selected': False, 'text': '<p>Declarative is not necessarily more (or less) pythonic than functional IMHO. I think a layered approach would be the best (from buttom up):</p>\n\n<ol>\n<li>A native layer that accepts and returns python data types.</li>\n<li>A functional dynamic layer.</li>\n<li>One or more declarative/object-oriented layers.</li>\n</ol>\n\n<p>Similar to <a href="http://elixir.ematia.de/trac/wiki" rel="nofollow noreferrer">Elixir</a> + <a href="http://www.sqlalchemy.org/" rel="nofollow noreferrer">SQLAlchemy</a>.</p>\n'}, {'answer_id': 335443, 'author': 'Suraj', 'author_id': 39446, 'author_profile': 'https://Stackoverflow.com/users/39446', 'pm_score': 1, 'selected': False, 'text': '<p>Personally, I would try to implement <a href="http://docs.jquery.com/Main_Page" rel="nofollow noreferrer">JQuery</a> like API in a GUI framework.</p>\n\n<pre><code>class MyWindow(Window):\n    contents = (\n        para(\'Hello World!\'),\n        button(\'Click Me\', id=\'ok\'),\n        para(\'Epilog\'),\n    )\n\n    def __init__(self):\n        self[\'#ok\'].click(self.message)\n        self[\'para\'].hover(self.blend_in, self.blend_out)\n\n    def message(self):\n        print \'You clicked!\'\n\n    def blend_in(self, object):\n        object.background = \'#333333\'\n\n    def blend_out(self, object):\n        object.background = \'WindowBackground\'\n</code></pre>\n'}, {'answer_id': 335887, 'author': 'Nick Retallack', 'author_id': 2653, 'author_profile': 'https://Stackoverflow.com/users/2653', 'pm_score': 2, 'selected': False, 'text': '<p>This is extremely contrived and not pythonic at all, but here\'s my attempt at a semi-literal translation using the new "with" statement.</p>\n\n<pre><code>with Shoes():\n  t = Para("Not clicked!")\n  with Button("The Label"):\n    Alert("You clicked the button!")\n    t.replace("Clicked!")\n</code></pre>\n\n<p>The hardest part is dealing with the fact that python will not give us anonymous functions with more than one statement in them.  To get around that, we could create a list of commands and run through those...</p>\n\n<p>Anyway, here\'s the backend code I ran this with:</p>\n\n<pre><code>context = None\n\nclass Nestable(object):\n  def __init__(self,caption=None):\n    self.caption = caption\n    self.things = []\n\n    global context\n    if context:\n      context.add(self)\n\n  def __enter__(self):\n    global context\n    self.parent = context\n    context = self\n\n  def __exit__(self, type, value, traceback):\n    global context\n    context = self.parent\n\n  def add(self,thing):\n    self.things.append(thing)\n    print "Adding a %s to %s" % (thing,self)\n\n  def __str__(self):\n    return "%s(%s)" % (self.__class__.__name__, self.caption)\n\n\nclass Shoes(Nestable):\n  pass\n\nclass Button(Nestable):\n  pass\n\nclass Alert(Nestable):\n  pass\n\nclass Para(Nestable):\n  def replace(self,caption):\n    Command(self,"replace",caption)\n\nclass Command(Nestable):\n  def __init__(self, target, command, caption):\n    self.command = command\n    self.target  = target\n    Nestable.__init__(self,caption)\n\n  def __str__(self):\n    return "Command(%s text of %s with \\"%s\\")" % (self.command, self.target, self.caption)\n\n  def execute(self):\n    self.target.caption = self.caption\n</code></pre>\n'}, {'answer_id': 336089, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 1, 'selected': False, 'text': '<p>Here\'s an approach that goes about GUI definitions a bit differently using class-based meta-programming rather than inheritance.</p>\n\n<p>This is largley Django/SQLAlchemy inspired in that it is heavily based on meta-programming and separates your GUI code from your "code code".  I also think it should make heavy use of layout managers like Java does because when you\'re dropping code, no one wants to constantly tweak pixel alignment.  I also think it would be cool if we could have CSS-like properties.</p>\n\n<p>Here is a rough brainstormed example that will show a column with a label on top, then a text box, then a button to click on the bottom which shows a message.</p>\n\n<pre>\nfrom happygui.controls import *\n\nMAIN_WINDOW = Window(width="500px", height="350px",\n    my_layout=ColumnLayout(padding="10px",\n        my_label=Label(text="What\'s your name kiddo?", bold=True, align="center"),\n        my_edit=EditBox(placeholder=""),\n        my_btn=Button(text="CLICK ME!", on_click=Handler(\'module.file.btn_clicked\')),\n    ),\n)\nMAIN_WINDOW.show()\n\ndef btn_clicked(sender): # could easily be in a handlers.py file\n    name = MAIN_WINDOW.my_layout.my_edit.text\n    # same thing: name = sender.parent.my_edit.text\n    # best practice, immune to structure change: MAIN_WINDOW.find(\'my_edit\').text\n    MessageBox("Your name is \'%s\'" % ()).show(modal=True)\n</pre>\n\n<p>One cool thing to notice is the way you can reference the input of my_edit by saying <code>MAIN_WINDOW.my_layout.my_edit.text</code>.  In the declaration for the window, I think it\'s important to be able to arbitrarily name controls in the function kwargs.</p>\n\n<p>Here is the same app only using absolute positioning (the controls will appear in different places because we\'re not using a fancy layout manager):</p>\n\n<pre>\nfrom happygui.controls import *\n\nMAIN_WINDOW = Window(width="500px", height="350px",\n    my_label=Label(text="What\'s your name kiddo?", bold=True, align="center", x="10px", y="10px", width="300px", height="100px"),\n    my_edit=EditBox(placeholder="", x="10px", y="110px", width="300px", height="100px"),\n    my_btn=Button(text="CLICK ME!", on_click=Handler(\'module.file.btn_clicked\'), x="10px", y="210px", width="300px", height="100px"),\n)\nMAIN_WINDOW.show()\n\ndef btn_clicked(sender): # could easily be in a handlers.py file\n    name = MAIN_WINDOW.my_edit.text\n    # same thing: name = sender.parent.my_edit.text\n    # best practice, immune to structure change: MAIN_WINDOW.find(\'my_edit\').text\n    MessageBox("Your name is \'%s\'" % ()).show(modal=True)\n</pre>\n\n<p>I\'m not entirely sure yet if this is a super great approach, but I definitely think it\'s on the right path.  I don\'t have time to explore this idea more, but if someone took this up as a project, I would love them.</p>\n'}, {'answer_id': 336525, 'author': 'samuraisam', 'author_id': 42751, 'author_profile': 'https://Stackoverflow.com/users/42751', 'pm_score': 2, 'selected': False, 'text': "<pre><code>## All you need is this class:\n\nclass MainWindow(Window):\n    my_button = Button('Click Me')\n    my_paragraph = Text('This is the text you wish to place')\n    my_alert = AlertBox('What what what!!!')\n\n    @my_button.clicked\n    def my_button_clicked(self, button, event):\n        self.my_paragraph.text.append('And now you clicked on it, the button that is.')\n\n    @my_paragraph.text.changed\n    def my_paragraph_text_changed(self, text, event):\n        self.button.text = 'No more clicks!'\n\n    @my_button.text.changed\n    def my_button_text_changed(self, text, event):\n        self.my_alert.show()\n\n\n## The Style class is automatically gnerated by the framework\n## but you can override it by defining it in the class:\n##\n##      class MainWindow(Window):\n##          class Style:\n##              my_blah = {'style-info': 'value'}\n##\n## or like you see below:\n\nclass Style:\n    my_button = {\n        'background-color': '#ccc',\n        'font-size': '14px'}\n    my_paragraph = {\n        'background-color': '#fff',\n        'color': '#000',\n        'font-size': '14px',\n        'border': '1px solid black',\n        'border-radius': '3px'}\n\nMainWindow.Style = Style\n\n## The layout class is automatically generated\n## by the framework but you can override it by defining it\n## in the class, same as the Style class above, or by\n## defining it like this:\n\nclass MainLayout(Layout):\n    def __init__(self, style):\n        # It takes the custom or automatically generated style class upon instantiation\n        style.window.pack(HBox().pack(style.my_paragraph, style.my_button))\n\nMainWindow.Layout = MainLayout\n\nif __name__ == '__main__':\n    run(App(main=MainWindow))\n</code></pre>\n\n<p>It would be relatively easy to do in python with a bit of that metaclass python magic know how. Which I have. And a knowledge of PyGTK. Which I also have. Gets ideas?</p>\n"}, {'answer_id': 336583, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 2, 'selected': False, 'text': '<p>If you use <a href="http://www.pygtk.org/" rel="nofollow noreferrer">PyGTK</a> with <a href="http://glade.gnome.org/" rel="nofollow noreferrer">glade</a> and <a href="http://www.pixelbeat.org/libs/libglade.py" rel="nofollow noreferrer">this glade wrapper</a>, then PyGTK actually becomes somewhat pythonic. A little at least.</p>\n\n<p>Basically, you create the GUI layout in Glade. You also specify event callbacks in glade. Then you write a class for your window like this:</p>\n\n<pre><code>class MyWindow(GladeWrapper):\n    GladeWrapper.__init__(self, "my_glade_file.xml", "mainWindow")\n    self.GtkWindow.show()\n\n    def button_click_event (self, *args):\n        self.button1.set_label("CLICKED")\n</code></pre>\n\n<p>Here, I\'m assuming that I have a GTK Button somewhere called <em>button1</em> and that I specified <em>button_click_event</em> as the <em>clicked</em> callback. The glade wrapper takes a lot of effort out of event mapping.</p>\n\n<p>If I were to design a Pythonic GUI library, I would support something similar, to aid rapid development. The only difference is that I would ensure that the widgets have a more pythonic interface too. The current PyGTK classes seem very C to me, except that I use foo.bar(...) instead of bar(foo, ...) though I\'m not sure exactly what I\'d do differently. Probably allow for a Django models style declarative means of specifying widgets and events in code and allowing you to access data though iterators (where it makes sense, eg widget lists perhaps), though I haven\'t really thought about it.</p>\n'}]
['https://Stackoverflow.com/questions/58711', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/745/']