Pyjamas Tutorial Part 2

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.

  1. Select the Pyjamas widgets needed to implement the UI elements.
  2. Select the Pyjamas panels needed to layout the UI elements.
  3. Implement the widgets and panels in StockWatcher.py.
  4. Test the layout.

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.

1. Selecting Pyjamas widgets to implement the UI elements

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.

Stock Data Table

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.

Buttons

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.

Input Box

Pyjamas provides several widgets to create fields that users can type in:

  • TextBox widget, a single-line text box
  • PassWordTextBox widget, a text box that visually masks input
  • TextArea widget, a multi-line text box
  • SuggestBox, displays a pre-configured set of items

StockWatcher users will type in a stock code which is single line of text; therefore, implement a TextBox widget.

Label

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.

2. Selecting panels to layout the UI elements

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.

Horizontal 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.

Vertical Panel

You want to lay out the remaining elements vertically.

  • the FlexTable widget: the stock table
  • the Add Stock panel: contains the input box and Add button
  • the Label widget: the timestamp

You’ll do this with a vertical panel. In the Java code, you’ll create a new instance of VerticalPanel and name it mainPanel.

Root Panel

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.

4. Implementing widgets and panels

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:

  1. Instantiate each widget and panel.
  2. Create the table that holds the stock data.
  3. Lay out the widgets using the Add Stock panel and the Main panel.
  4. Associate the Main panel with the Root panel.
  5. Move the cursor focus to the input box.

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.

1. Instantiate each widget and panel

Instantiate each widget and panel using class field initializers.
Create a Stockwatcher.py file und fill it with the following code
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()

2. Create a table for stock data

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.

  1. Create table for stock data.
    In the onModuleLoad method, replace the TODO comment with the highlighted code.
    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()

3. Lay out the widgets

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.

  1. Lay out the widgets in the Add Stock panel and the Main panel.
    In the onModuleLoad method, replace the TODO comment with the highlighted code.
    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()

4. Associate the Main panel with the Root panel

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.

  1. Associate the Main panel with the host page via the Root panel.
    In the onModuleLoad method, replace the TODO comment with the highlighted code.
    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()

5. Move cursor focus to the input box

Finally, move the cursor focus to the input box so, when StockWatcher loads, the user can begin adding stocks.

  1. In the onModuleLoad method, replace the TODO comment with the highlighted code.
    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()

Summary

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()

5. Testing the layout

  1. Save the edited files.
    Save StockWatcher.py
  2. Compile the edited files.
    Compile your StockWatcher.py in debugging mode path/to/pyjamas/bin/pyjsbuild .py StockWatcher.py -d
  3. Launch StockWatcher in in your browser.
    Open output/StockWatcher.htmlfrom your StockWatcher directory in your browser.
  4. You should see your first iteration of StockWatcher
    StockWatcher displays the header of the flex table, the input box and the Add button. You haven’t set the text for the Label, yet; so, it isn’t displayed. You’ll do that after you’ve implemented the stock refresh mechanism.
  5. Leave StockWatcher running in hosted mode.
    In the rest of this tutorial, you’ll frequently be testing changes in hosted mode.

Refreshing Hosted Mode

Best Practices: You should compile your app and reload your browser very often. Don’t do to many steps at once.

What’s Next

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.

Advertisements

3 thoughts on “Pyjamas Tutorial Part 2

  1. vamsi

    Hey i was following your tutorial and when i open the Stockwatcher.html file on a browser i get “Stockwatcher TypeError: Stockwatcher.Stockwatcher is not a function” error on the page.
    could you help me with this

  2. rockiger Post author

    Sorry, I can’t help you. It was years ago I wrote this tutorial. Did you follow the tutorial closely? Maybe you should refer to the official Pyjamas site.

  3. Ikechukwu

    I got a similar error. Check to see if your if statement is indented too far. If its within the class, it won’t work.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s