Need to learn a lot of stuff?
In this article I wrote about a software, that help you learn us much as possible: The perfect vocabulary trainer
In this article I wrote about a software, that help you learn us much as possible: The perfect vocabulary trainer
This tutorial series is based on the Getting Started tutorial for GWT.
Part 2: Building the User Interface
At this point, you’ve created all the elements of the interface. Like many user interface frameworks, Pyjamas is event-based. This means that the code executes in response to some event occurring. Most often, that event is triggered by the user, who uses the mouse or keyboard to interact with the application interface.
In this section, you’ll wire up your widgets to listen for and handle mouse and keyboard events.
Let’s review the StockWatcher requirements to see what events occur.
| Task | UI Event (Trigger mechanism) | Response |
|---|---|---|
| User enters a stock code. | Clicks the Add button or presses return in the input box. |
|
| User deletes stock from the table. | Presses the Remove button. |
|
provides a number of different event handler interfaces. To handle click events on the Add and Remove buttons, you’ll use the build in ClickHandler class of the Button. To handle keyboard events in the input box, you’ll use the KeyPressHandler class.
Events in Pyjamas use the event handler model similar to other user interface frameworks. To subscribe to an event, you pass a particular event handler interface to the appropriate widget. An event handler class defines one or more methods that the widget then calls to announce (publish) an event.
One way StockWatcher users can enter a stock code is by using their mouse to click on the Add button.
You’ll handle the Add button’s click event by just assigning a function to the button, which fires when the user clicks on the widget.
When the user clicks on the Add button, StockWatcher should respond by adding the stock to the stock table. So, to handle the click event, call the addStock method. You haven’t written the addStock method yet; you’ll create a stub and then code it in the next section.
from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.VerticalPanel import VerticalPanel
from pyjamas.ui.FlexTable import FlexTable
from pyjamas.ui.HorizontalPanel import HorizontalPanel
from pyjamas.ui.TextBox import TextBox
from pyjamas.ui.Button import Button
from pyjamas.ui.Label import Label
from pyjamas import Window
class Stockwatcher:
# Entry point method.
def __init__(self):
# declare interface widgets
self.mainPanel = VerticalPanel()
self.stocksFlexTable = FlexTable()
self.addPanel = HorizontalPanel()
self.newSymbolTextBox = TextBox()
self.addStockButton = Button("Add", getattr(self, "addStock"))
self.lastUpdatedLabel = Label()
def addStock(self):
# Add stock to FlexTable. Executed when the user clicks the
# addStockButton or presses enter in the newSymbolTextBox.
def onModuleLoad(self):
# Create table for stock data.
self.stocksFlexTable.setText(0, 0, "Symbol")
self.stocksFlexTable.setText(0, 1, "Price")
self.stocksFlexTable.setText(0, 2, "Change")
self.stocksFlexTable.setText(0, 3, "Remove")
# Assemble Add Stock panel.
self.addPanel.add(self.newSymbolTextBox)
self.addPanel.add(self.addStockButton)
#Assemble Main panel.
self.mainPanel.add(self.stocksFlexTable)
self.mainPanel.add(self.addPanel)
self.mainPanel.add(self.lastUpdatedLabel)
#Associate the Main panel with the HTML host page.
RootPanel().add(self.mainPanel)
# Move cursor focus to the input box.
self.newSymbolTextBox.setFocus(True)
if __name__ == '__main__':
app = Stockwatcher()
app.onModuleLoad()
In addition to using the Add button, StockWatcher users can enter a stock code without taking their hands from the keyboard by pressing return in the input box.
To subscribe to keyboard events, you can call the addKeyPressHandler(KeyPressHandler) method and pass it a KeyPressHandler.
def onKeyDown(self, sender, keycode, modifiers):
pass
def onKeyUp(self, sender, keycode, modifiers):
pass
def onKeyPress(self, sender, keycode, modifiers):
if sender == self.newSymbolTextBox and \
keycode == KeyboardListener.KEY_ENTER:
self.addStock()
The event handlers are now wired up and ready for an event. Your next step is to fill out the stub addStock method.
At this point, StockWatcher should be listening for user input, a mouse or keyboard event that signals the user has entered a stock code. So next you’ll test whether or not the event handler interfaces are working by coding the response that StockWatcher should make when it detects an event: add the stock. StockWatcher responds on the client side without sending any requests back to server or reloading the HTML page.
In StockWatcher, users will enter the stock codes of the stocks they want to monitor one at a time into the input box. When they press Enter or click on the Add button, you want StockWatcher to respond as follows:
In this section, you’ll code the first response, validating the input, just to see if the event handler interfaces are working. In the next section, Coding Functionality on the Client, you’ll code the rest of the steps to add the stock.
You’ll implement this functionality in the addStock method.
You want verify that the stock code entered is valid. Rather than verify whether the user input matches an actual stock code, for the purposes of this tutorial, you’ll just perform a simple character validity check.
First, extract the stock code. To retrieve the text in the TextBox widget use its getText method.
Next, ensure that the charcters are not within the set of illegal characters you specify. After you’ve converted the user input to a standard form, use a regular expression to check its format. Remember to use regular expressions.
If the input is valid, clear the text box so the user can add another stock code.
Finally, if the input is not valid, warn users via a dialog box.
def addStock(self):
# Add stock to FlexTable. Executed when the user clicks the
# addStockButton or presses enter in the newSymbolTextBox.
symbol = self.newSymbolTextBox.getText()
self.newSymbolTextBox.setText("")
self.newSymbolTextBox.setFocus(True)
symbol = symbol.upper().strip()
if not testRegEx(symbol):
Window.alert("Please choose a different name than %s.\n\
The Name should only contain number \
and characters" % (symbol))
return
# TODO Don't add the stock if it's already in the table.
# TODO Add the stock to the table.
# TODO Add a button to remove this stock from the table.
# TODO Get the stock price.
}
def testRegEx(string):
"""Test a regular expression"""
JS("""
var re = new RegExp("^[0-9a-zA-Z\s]{1,30}$");
return re.test(string);
""")
At this point you should be able to enter text in the input box. If you use an illegal character, a dialog box should pop up and display a warning. Try it and see.

At this point you’ve implemented event handler interfaces for mouse and keyboard events that signal the user has entered a stock. Stockwatcher responds by validating the input.
From now on, you should be able to go on your own.
You could improve the client that it adds the stock to the table and provide a button to remove it. See the original Google tutorial for inspiration.
Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 2.5 Attribution License.
This tutorial series is based on the Getting Started tutorial for GWT.
Part1: Designing the Application
At this point, you’ve created the components of the StockWatcher project and reviewed its functional requirements and UI design. In this section, you’ll build the user interface out of Pyjamas widgets and panels.
Pyjamas shields you from worrying too much about cross-browser incompatibilities. If you clonstructonstruct the interface with Pyjamas widgets and composites, your application will work similarly on the most recent versions of Firefox, Internet Explorer, Opera, and Safari. However, DHTML user interfaces remain remarkably quirky; therefore, you still must test your applications thoroughly on every browser.
First, look at the Widget Gallery and select the Pyjamas widget for each UI element. The class names of Pyjamas and Pyjamas are the same in most cases.
In the Widget Gallery the widgets have a default style and so they don’t look exactly as they will in the final implementation of StockWatcher. Don’t worry about that now. First you’ll focus on getting the widgets working. Then, in Applying Styles, you’ll change their appearance with CSS.
Pyjamas provides a special table widget called a FlexTable. The FlexTable widget creates cells on demand. This is just what you need for the table containing the stock data because you don’t know how many stocks the user will add. A table implemented with the FlexTable widget will expand or collapse as the user adds or removes stocks.
Whenever possible, Pyjamas defers to browsers’ native user interface elements. For instance, a Button widget becomes a true HTML <button> rather than a synthetic button-like widget that’s built, for example, from a <div>. This means that Pyjamas buttons render appropriately in different browsers and on different client operating systems. The benefit of using native browser controls is that they are fast, accessible, and most familiar to users. Also, they can be styled with CSS.
Pyjamas provides several widgets to create fields that users can type in:
StockWatcher users will type in a stock code which is single line of text; therefore, implement a TextBox widget.
In contrast with the Button widget, the Label widget does not map to the HTML <label> element, used in HTML forms. Instead it maps to a <div> element which contains arbitrary text, not interpreted as HTML. As a <div> element, it is a block-level element rather than an inline element.
<div class="gwt-Label">Last update : Oct 1, 2008 1:31:48 PM</div>
If you’re interested in taking a peek at the API reference for the Pyjamas widgets you’ll use to build the StockWatcher interface, click on the links in the table below.
| UI element | Pyjamas implementation |
|---|---|
| a table: to hold the stock data | FlexTable widget |
| two buttons: one to add stocks and one to remove them | Button widget |
| an input box: to enter the stock code | TextBox widget |
| a timestamp: to show the time and date of the last refresh | Label widget |
| a logo | image file referenced from HTML host page |
| a header | static HTML in HTML host page |
| indicate whether the change in price was positive or negative using colors | dynamic CSS |
In Depth: If you don’t find a widget that meets the functional requirements of your application, you can create your own. For details on creating composite widgets or widgets from scratch using Java or JavaScript, see the Developer’s Guide, Creating Custom Widgets.
Now that you know what widgets you’ll use, you’ll decide how to lay them out using Pyjamas panels. Pyjamas provides several types of panels to manage the layout. Panels can be nested within other panels. This is analogous to laying out your web page in HTML using nested div elements or tables. For StockWatcher, you’ll use a Horizontal panel nested within a Vertical panel.
The two elements used to add a stock—the input box for typing in a new stock symbol and the Add button—are closely related functionally and you want keep them together visually. To lay them out side-by-side, you’ll put the TextBox widget and a Button widget in a horizontal panel. In the Java code, you’ll create a new instance of HorizontalPanel and name it addPanel.
You want to lay out the remaining elements vertically.
You’ll do this with a vertical panel. In the Java code, you’ll create a new instance of VerticalPanel and name it mainPanel.
There is one more panel you need which is not visible in the user interface: a Root panel. A Root panel is the container for the dynamics elements of your application. It is at the top of any Pyjamas user interface hierarchy. There are two ways you can use a Root panel, either to generate the entire body of the page or to generate specific elements embedded in the body.
The Root panel works by wrapping an element in the HTML host page. By default (that is, if you don’t add any placeholders in the host page) the Root panel wraps the body element. However, you can wrap any element if you name it and then, when you call the Root panel, pass the the name as a parameter. You’ll how this works in the next two sections when you do it for StockWatcher.
RootPanel('').add(self.somethin) # Default. Wraps the HTML
# body element.
RootPanel('stocklist').add(self.something) # Wraps any HTML
# element with an id
# of "stockList"
A host page can contain multiple Root panels. For example, if you’re embedding multiple widgets or panels into a host page, each one can be implemented independently of the others, wrapped in its own Root panel.
Next you will construct the user interface from Pyjamas widgets and panels.
Most of the UI is displayed as soon as StockWatcher starts up. So you’ll implement them in the onModuleLoad method. In this section, you will:
You can follow this section of the tutorial step-by-step, or you can cut and paste the entire block of code from the Summary at the end.
from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.VerticalPanel import VerticalPanel
from pyjamas.ui.FlexTable import FlexTable
from pyjamas.ui.HorizontalPanel import HorizontalPanel
from pyjamas.ui.TextBox import TextBox
from pyjamas.ui.Button import Button
from pyjamas.ui.Label import Label
class Stockwatcher:
# Entry point method.
def __init__(self):
#declare interface widgets
self.mainPanel = VerticalPanel()
self.stocksFlexTable = FlexTable()
self.addPanel = HorizontalPanel()
self.newSymbolTextBox = TextBox()
self.addStockButton = Button("Add")
self.lastUpdatedLabel = Label()
# TODO Create table for stock data.
# TODO Assemble Add Stock panel.
# TODO Assemble Main panel.
# TODO Associate the Main panel with the HTML host page.
# TODO Move cursor focus to the input box.
if __name__ == '__main__':
app = Stockwatcher()
app.onModuleLoad()
Implement the table that will hold the stock data. Set up the header row that displays when the user launches StockWatcher. To do this, use the setText method to create labels in the heading of each column: Symbol, Price, Change, Remove.
from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.VerticalPanel import VerticalPanel
from pyjamas.ui.FlexTable import FlexTable
from pyjamas.ui.HorizontalPanel import HorizontalPanel
from pyjamas.ui.TextBox import TextBox
from pyjamas.ui.Button import Button
from pyjamas.ui.Label import Label
class Stockwatcher:
# Entry point method.
def __init__(self):
#declare interface widgets
self.mainPanel = VerticalPanel()
self.stocksFlexTable = FlexTable()
self.addPanel = HorizontalPanel()
self.newSymbolTextBox = TextBox()
self.addStockButton = Button("Add")
self.lastUpdatedLabel = Label()
def onModuleLoad(self):
# Create table for stock data.
self.stocksFlexTable.setText(0, 0, "Symbol")
self.stocksFlexTable.setText(0, 1, "Price")
self.stocksFlexTable.setText(0, 2, "Change")
self.stocksFlexTable.setText(0, 3, "Remove")
# TODO Assemble Add Stock panel.
# TODO Assemble Main panel.
# TODO Associate the Main panel with the HTML host page.
# TODO Move cursor focus to the input box.
if __name__ == '__main__':
app = Stockwatcher()
app.onModuleLoad()
To lay out the widgets, you’ll assemble two panels, the Add Stock panel and the Main panel. First assemble the the Add Stock panel, a horizontal panel which wraps the input box and the Add button. Then assemble the Main panel, a vertical panel that specifies the layout of the stock list table, the Add Stock panel, and the timestamp.
from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.VerticalPanel import VerticalPanel
from pyjamas.ui.FlexTable import FlexTable
from pyjamas.ui.HorizontalPanel import HorizontalPanel
from pyjamas.ui.TextBox import TextBox
from pyjamas.ui.Button import Button
from pyjamas.ui.Label import Label
class Stockwatcher:
# Entry point method.
def __init__(self):
#declare interface widgets
self.mainPanel = VerticalPanel()
self.stocksFlexTable = FlexTable()
self.addPanel = HorizontalPanel()
self.newSymbolTextBox = TextBox()
self.addStockButton = Button("Add")
self.lastUpdatedLabel = Label()
def onModuleLoad(self):
# Create table for stock data.
self.stocksFlexTable.setText(0, 0, "Symbol")
self.stocksFlexTable.setText(0, 1, "Price")
self.stocksFlexTable.setText(0, 2, "Change")
self.stocksFlexTable.setText(0, 3, "Remove")
# Assemble Add Stock panel.
self.addPanel.add(self.newSymbolTextBox)
self.addPanel.add(self.addStockButton)
#Assemble Main panel.
self.mainPanel.add(self.stocksFlexTable)
self.mainPanel.add(self.addPanel)
self.mainPanel.add(self.lastUpdatedLabel)
# TODO Associate the Main panel with the HTML host page.
# TODO Move cursor focus to the input box.
if __name__ == '__main__':
app = Stockwatcher()
app.onModuleLoad()
In order for any Pyjamas widget or panel to be embedded in the HTML host page, it must be contained within a Root panel. Associate the Root panel with Vertical panel, mainPanel. The Root panel wraps the HTML element in StockWatcher’s host page that has an id of “stocklist”. In this case, it is a <div> element.
from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.VerticalPanel import VerticalPanel
from pyjamas.ui.FlexTable import FlexTable
from pyjamas.ui.HorizontalPanel import HorizontalPanel
from pyjamas.ui.TextBox import TextBox
from pyjamas.ui.Button import Button
from pyjamas.ui.Label import Label
class Stockwatcher:
# Entry point method.
def __init__(self):
#declare interface widgets
self.mainPanel = VerticalPanel()
self.stocksFlexTable = FlexTable()
self.addPanel = HorizontalPanel()
self.newSymbolTextBox = TextBox()
self.addStockButton = Button("Add")
self.lastUpdatedLabel = Label()
def onModuleLoad(self):
# Create table for stock data.
self.stocksFlexTable.setText(0, 0, "Symbol")
self.stocksFlexTable.setText(0, 1, "Price")
self.stocksFlexTable.setText(0, 2, "Change")
self.stocksFlexTable.setText(0, 3, "Remove")
# Assemble Add Stock panel.
self.addPanel.add(self.newSymbolTextBox)
self.addPanel.add(self.addStockButton)
#Assemble Main panel.
self.mainPanel.add(self.stocksFlexTable)
self.mainPanel.add(self.addPanel)
self.mainPanel.add(self.lastUpdatedLabel)
#Associate the Main panel with the HTML host page.
RootPanel().add(self.mainPanel)
# TODO Move cursor focus to the input box.
if __name__ == '__main__':
app = Stockwatcher()
app.onModuleLoad()
Finally, move the cursor focus to the input box so, when StockWatcher loads, the user can begin adding stocks.
from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.VerticalPanel import VerticalPanel
from pyjamas.ui.FlexTable import FlexTable
from pyjamas.ui.HorizontalPanel import HorizontalPanel
from pyjamas.ui.TextBox import TextBox
from pyjamas.ui.Button import Button
from pyjamas.ui.Label import Label
class Stockwatcher:
# Entry point method.
def __init__(self):
#declare interface widgets
self.mainPanel = VerticalPanel()
self.stocksFlexTable = FlexTable()
self.addPanel = HorizontalPanel()
self.newSymbolTextBox = TextBox()
self.addStockButton = Button("Add")
self.lastUpdatedLabel = Label()
def onModuleLoad(self):
# Create table for stock data.
self.stocksFlexTable.setText(0, 0, "Symbol")
self.stocksFlexTable.setText(0, 1, "Price")
self.stocksFlexTable.setText(0, 2, "Change")
self.stocksFlexTable.setText(0, 3, "Remove")
# Assemble Add Stock panel.
self.addPanel.add(self.newSymbolTextBox)
self.addPanel.add(self.addStockButton)
#Assemble Main panel.
self.mainPanel.add(self.stocksFlexTable)
self.mainPanel.add(self.addPanel)
self.mainPanel.add(self.lastUpdatedLabel)
#Associate the Main panel with the HTML host page.
RootPanel().add(self.mainPanel)
# Move cursor focus to the input box.
self.newSymbolTextBox.setFocus(True)
if __name__ == '__main__':
app = Stockwatcher()
app.onModuleLoad()
Here’s what you’ve done to this point.
from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.VerticalPanel import VerticalPanel
from pyjamas.ui.FlexTable import FlexTable
from pyjamas.ui.HorizontalPanel import HorizontalPanel
from pyjamas.ui.TextBox import TextBox
from pyjamas.ui.Button import Button
from pyjamas.ui.Label import Label
class Stockwatcher:
# Entry point method.
def __init__(self):
#declare interface widgets
self.mainPanel = VerticalPanel()
self.stocksFlexTable = FlexTable()
self.addPanel = HorizontalPanel()
self.newSymbolTextBox = TextBox()
self.addStockButton = Button("Add")
self.lastUpdatedLabel = Label()
def onModuleLoad(self):
# Create table for stock data.
self.stocksFlexTable.setText(0, 0, "Symbol")
self.stocksFlexTable.setText(0, 1, "Price")
self.stocksFlexTable.setText(0, 2, "Change")
self.stocksFlexTable.setText(0, 3, "Remove")
# Assemble Add Stock panel.
self.addPanel.add(self.newSymbolTextBox)
self.addPanel.add(self.addStockButton)
#Assemble Main panel.
self.mainPanel.add(self.stocksFlexTable)
self.mainPanel.add(self.addPanel)
self.mainPanel.add(self.lastUpdatedLabel)
#Associate the Main panel with the HTML host page.
RootPanel().add(self.mainPanel)
# Move cursor focus to the input box.
self.newSymbolTextBox.setFocus(True)
if __name__ == '__main__':
app = Stockwatcher()
app.onModuleLoad()
StockWatcher.pypath/to/pyjamas/bin/pyjsbuild .py StockWatcher.py -doutput/StockWatcher.htmlfrom your StockWatcher directory in your browser.
Best Practices: You should compile your app and reload your browser very often. Don’t do to many steps at once.
At this point you’ve built the basic UI components of StockWatcher by implementing Pyjamas widgets and panels. The widgets don’t respond to any input yet.
Now you’re ready to code event handling on the client. You’ll wire up the widgets to listen for events and write the code that responds to those events.
Step 3: Managing Events on the Client
Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 2.5 Attribution License.
I will post a tutorial series about Pyjamas the superb Python to Javascript compiler. This tutorial series will be based on the Getting Started tutorial for GWT. I will assume that you have Pyjamas correctly installed on your plattform (Linux, Mac, Win).
In this section, you’ll review the functional requirements and design the user interface.
Initially you want the StockWatcher application to do six things.

After studying StockWatcher’s functional requirements, you decide you need these UI elements.
Pyjamas does not dictate how you lay out your HTML page. A GWT application can take up the entire browser window, as it does in the startup application. Or it can be embedded in an existing page, as it is in the Getting Started page of this tutorial.
The StockWatcher application contains both static and dynamic elements. The logo and the header “StockWatcher” are static elements in the HTML host page. All the other elements are created programmatically using Pyjamas.
At this point you’ve reviewed StockWatcher’s functional requirements. You have a clear idea of what StockWatcher does. You know what UI elements you need to implement and how you want to lay them out.
Now you’re ready to build the user interface using GWT widgets and panels.
Coming soon:
Part 2: Building the User Interface
Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 2.5 Attribution License.
In the first installation of this series I told you, that I think that the command line is the second important tool, to get you faster with your Ubuntu usage. Actually the command line is the most powerful toy you can use in the Linux world. Today I want to show a terminal emulator that has its root in the ego-shooter Doom.
Most Ubuntu-Rockstars have always a terminal window opened, that enables them to punch in some useful and time saving commands. The drawback of this method is that the terminal is just another application on the desktop and could be hidden behind some different app or could be minimized, that you have activate it via the window list.
An nice alternative is Guake.
To install Guake you have to download this package from their website and then install it via the Gedebi installer. As with Gnome-Do you should add Guake to your autostart list.
After you installed Guake you should hit the systray icon with your right mouse button and choose preference. In the preferences dialog you should set the hotkey for the roll down. I use the Menu-key, because I have no further use for it.
You can imagine Guake like a roller shutter that covers the other windows as you hit the hotkey.
Now you are free to type in some commands.
As soon as you hit the hotkey again Guake rolls up.
In contrast to Gnome-Do Guake is not of much use unless you are familar with the command line. If you are not using the command line already, you should change that as soon as possible. You can find a short introduction here and a useful sheat-cheat here.
I want to write a little series about how I use Ubuntu and what I got used to speed up my work with Ubuntu. This article is written for people who have just migrated to Ubuntu or Linux and as well for more experienced users. These series is based on my personal experience.
The first episode will be about Gnome-Do. Gnome-Do speeds up my work like no second application. At most the command line is as useful for me.
First you have to install Gnome-Do.
First you have to add
## gnome-do
deb http://ppa.launchpad.net/do-core/ubuntu hardy main
deb-src http://ppa.launchpad.net/do-core/ubuntu hardy main
to your “/etc/apt/sources.list”. After that you type in the commandline:
sudo aptitude update
sudo aptitude install gnome-do gnome-do-plugins

To open the folder “Businessplan” (screenshot) on my computer I just have to press WIN+Space, type “bus” and then hit Enter. Boom, the folder opens immediately. The same way you can start programs, twitter, create Tomboy-Notes and much more. Best you add Gnome-Do to your autostart today.
I am currently learning Pyjamas, the Python to Javascript compiler. This means writing Javascript without knowing Javascript.
I am at the very begining of my journey. As the title suggests, I will post tiny bits of what I learned about Pyjamas and what I think could be useful to others, too.
This is a living post, I will add content when I learn something new.
Create div in your html-template, where you want to place your app
<div id="my-app"></div>
Then call the div in your python code like this:
RootPanel("my-app").add(MyWidget(.....))
If you want to connect a button to a method:
Don’t do:
class Example:
def __init__(self):
...
self.exButton = Button("Add", self.exMethod)
...
def exMethod(self):
...
Instead do:
class Example:
def __init__(self):
...
self.exButton = Button("Add",self)
...
def onClick(self, sender):
if sender == self.exButton:
self.exMethod()
def exMethod(self):
...
This way should not only used with buttons, but it should also used with any other widget from Pyjamas.
If your are using Pyjamas-0.5 update to to the newest version of Pyjamas!
I had some trouble to get the web2py example running. At the the end it came out the problem was Pyjamas-0.5. So update now!
Now back to learning…
Last weekend I was at FrOSCon in St. Augustin, Germany.
The FrOSCon is one of the three greatest open-source conferences in Germany. I thought this should be a good place to meet influencers and learn about the open-source market in general.
I got to know Dries Buytert the project lead of Drupal CMS. He held a very interesting key note about growing a (oss) community. Dries is a very nice guy, he finds a good balance between being a geek and being a great communicator. Dries is an entrepreneur also, he founded Aquia, a Drupal based startup, that wants to be to Drupal what Redhat is to Linux. I have no doubt that Dries will succeed with his company.

Dries preparing his key note (shot from my Nokia N810)
I learned a lot about the my customers, that they:
Besides that I got to know a bunch of people that work in neighbor markets that could be helpful in the future.
At the end the FROSCON was a very interesting event for me, that was fun, too.