If you are a Python developer and don’t like JS a lot then look at Pyjamas desktop it will run on Web as well as desktop applications. It’s based on google webkit, pyjamas is a cross-browser web application development API. it looks like a desktop API, but underneath, pyjamas is an AJAX library and a comprehensive widget set (implemented as AJAX but you never go anywhere near JavaScript, because at the core of pyjamas is a python-to-javascript compiler).

What is Pyjamas desktop?

It is a cross-platform application development API. like pygtk2, like python-qt4 and wxWidgets, is very powerful as you can do the followings:

load complete html pages

complete stylesheets

even execute bits of javascript

So, how you can do it? answer is pretty simple because it’s based on webkit. so you get access to the DOM model, you get full HTML compliance, wickedly-fast javascript execution, media plugins, CSS stylesheets – everything.

You should have exposure of developing a 10 line “Loader” HTML page and an optional CSS, thats cool isn’t it?. Even the CSS file is optional because you are provided via the Pyjamas API with access to some of the more useful CSS features such as setting the width and height, and you can if you wish to directly manipulate the CSS style properties from your application.

in short, you get to write apps that look like they ought to be running on a desktop, and pyjamas takes care of all the nasty browser tricks that you would normally perform in order to make it cross browser compatible for safari, opera, IE7, IE6, firefox, mozilla, midori etc.

Lets take a Hello World Example

1

2

3

4

5

6

7

8

9

<html>

<head>

<meta name="pygwt:module"content="Hello">

<title>Hello</title>

</head>

<body bgcolor="white">

<script language="javascript"src="pygwt.js"></script>

</body>

</html>

1

2

3

4

5

6

7

8

9

10

11

fromui importButton,RootPanel,Label

importWindow

defgreet(sender):Window.alert("Hello, AJAX!")

classHello:

defonModuleLoad(self):

b=Button("Click me",greet)

l=Label("hello world")

RootPanel().add(b)

RootPanel().add(l)

Now, lets look at Pyjamas Desktop Widgets

An important part of a widget toolkit is being able to write your own widgets. In many widget sets, you are confronted immediately with a quite complex set of unusual-looking functions – paint, draw, refresh and other manipulations. Pyjamas has none of that: in both Pyjamas and Pyjamas-Desktop you’re manipulating the DOM model – an HTML page – as if it was an XML document. Pyjamas provides a module which makes the job of controlling the underlying DOM model that much easier, and this tutorial shows step-by-step how to go about creating your own widget.

Vertical Slider

We start off by importing the DOM model and, because the slider will receive mouse (and later keyboard) events, we base it on FocusWidget. FocusWidget has the means to add keyboard and event listeners, set a “tab order” index, and to set and clear focus:

1

2

frompyjamas importDOM

frompyjamas.ui importFocusWidget

So, we derive our class from FocusWidget. We don’t declare a width and height as parameters, because Pyjamas Widgets are based on HTML principles: DOM models. So, you either set the CSS “Class” with setStyleName(), or you use the Pyjamas Widget functions setWidth() and setHeight(). We do however want to pass in the slider’s minimum, maximum and default values, and we may also want to keep track of who might be interested to know that the slider’s value has changed.

1

2

3

4

5

6

7

8

9

10

11

12

13

classVerticalDemoSlider(FocusWidget):

def__init__(self,min_value,max_value,start_value=None):

element=DOM.createDiv()

FocusWidget.__init__(self,element)

self.min_value=min_value

self.max_value=max_value

ifstart_value isNone:

start_value=min_value

self.value=start_value

self.valuechange_listeners=[]

Here also is the first actual bit of underlying HTML / DOM model showing through: we’re basing the widget on a “div” tag, hence we call DOM.createDiv() and set that as the FocusWidget’s element. (Immediately, therefore, you can see that the Pyjamas Widgets are effectively… “guardian” classes that look after and manipulate bits of the underlying DOM model, making the whole process of creating and maintaining your application just that little bit easier to understand). We’re also going to copy what AbsolutePanel.__init__() does, making the container DIV free-moving, and we’re also going to throw in a second hard-coded “div” for the actual slider handle:

1

2

3

4

5

DOM.setStyleAttribute(element,"position","relative")

DOM.setStyleAttribute(element,"overflow","hidden")

self.handle=DOM.createDiv()

DOM.appendChild(element,self.handle)

Then, as this is just a demonstration, we’re going to hand-code the slider handle with some attributes, making it 10 pixels high, a border of 1 pixel, fixing it to be the same width as the Widget, and making it a grey colour. A much better way to do this would be to set a CSS stylesheet where people could over-ride all these settings. Note that we don’t use DOM.setAttribute() to set the border, width and height. You should consult HTML specifications: you will find that “border” is an attribute for DOM tags such as “table”. So, if you try to call DOM.setAttribute() on a DIV tag, you’ll find that it silently fails in the browser – or if you remember, and examine the Javascript Console, you might be lucky and find a warning. However, if you try the same thing under Pyjamas-Desktop you will be rewarded with a much more useful run-time error. The upshot is: pay attention to the underlying DOM model, and remember to simultaneously develop your app using both Pyjamas and Pyjamas-Desktop, to save yourself a great deal of time. If you want to set a border on a “div” tag, you must set it as a CSS Style attribute:

1

2

3

4

DOM.setStyleAttribute(self.handle,"border","1px")

DOM.setStyleAttribute(self.handle,"width","100%")

DOM.setStyleAttribute(self.handle,"height","10px")

DOM.setStyleAttribute(self.handle,"backgroundColor","#808080")

Testing

With the basic beginnings, it’s enough to test out, to see if we have it working. If all we wanted was a little grey box in our widget, we’d be entirely done.

1

2

3

4

5

6

7

8

9

10

11

""" testing our demo slider

"""

frompyjamas.ui importRootPanel

frompyjamas.Controls importVerticalDemoSlider

classControlDemo:

defonModuleLoad(self):

b=VerticalDemoSlider(0,100)

RootPanel().add(b)

b.setWidth("20px")

b.setHeight("100px")

One thing I love about Pyjamas: this is enough code to do exactly what you want: create our slider, add it to the root panel, set its width to 20 pixels and the height to 100. Couldn’t get any easier. A quick run of this code shows that yes, indeed, we have a little grey box, which is very exciting. Next on the list is to make it move, and for that, we’ll add a “click listener”.

Making it move

To receive a click event, we use FocusWidget.addClickListener(). We’re going to make the widget itself receive the mouse click event. Looking at FocusWidget.onBrowserEvent(), we can see that we must add a function called onClick() to our VerticalDemoSlider. As we want to know where the mouse was clicked, we will need to add two arguments to the onClick() function, in order to receive the mouse event object as the second. Then, we simply take the mouse event y position, the absolute location of the container, and the “offset height” of the widget, do a little math and, copying some lines of code from AbsolutePanel.setWidgetPosition, we can change the location of the slider handle:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

defonClick(self,sender,event):

# work out the relative position of cursor

mouse_y=DOM.eventGetClientY(event)-\

DOM.getAbsoluteTop(sender.getElement())

self.moveSlider(mouse_y)

defmoveSlider(self,mouse_y):

relative_y=mouse_y-DOM.getAbsoluteTop(self.getElement())

widget_height=self.getOffsetHeight()

# limit the position to be in the widget!

ifrelative_y<0:

relative_y=0

height_range=widget_height-10# handle height is hard-coded

ifrelative_y>=height_range:

relative_y=height_range

# move the handle

DOM.setStyleAttribute(self.handle,"top","%dpx"%relative_y)

DOM.setStyleAttribute(self.handle,"position","absolute")

Okay – let’s test it! Save, run… lights, camera, action, aaand… nothing. huh. What have we done wrong? Oh yes, we forgot a very important line. Go back to VerticalDemoSlider.__init__ and add this, at the end, and try again:

1

self.addClickListener(self)

Amazing! We have a slider widget! A single-click moves the slider to where you clicked the mouse. Notice how the slider centre moves to where your mouse pointer actually points to: this is entirely a fluke, and is probably due to bugs in the CSS style implementation of your browser. Notice also that we haven’t actually set the value of the “slider”, but there’s enough maths to calculate it. We can add these extra lines on to the end of moveSlider():

1

2

3

val_diff=self.max_value-self.min_value

new_value=((val_diff*relative_y)/height_range)+self.min_value

self.setValue(new_value)

Then, we also add a setValue() function, which not only records the new value but also notifies any listeners. Copying the style of Label and other widgets’ addClickListener() and removeClickListener() functions, we’re doing addControlValueListener() and removeControlValueListener() to match.

1

2

3

4

5

6

7

8

9

10

11

12

defsetValue(self,new_value):

old_value=self.value

self.value=new_value

forlistener inself.valuechange_listeners:

listener.onControlValueChanged(self,old_value,new_value)

defaddControlValueListener(self,listener):

self.valuechange_listeners.append(listener)

defremoveControlValueListener(self,listener):

self.valuechange_listeners.remove(listener)

Now we should really see if that works. In the “test code”, add these extra lines to ControlDemo.onModuleLoad() and also add the additional function onControlValueChanged:

1

2

3

4

5

6

b.addControlValueListener(self)

self.label=Label("Not set yet")

RootPanel().add(self.label)

defonControlValueChanged(self,slider,old_value,new_value):

self.label.setText("Value: %d"%int(new_value))

Leave me a comment and let me hear your opinion. If you’ve got any thoughts, comments or suggestions for things we could add, leave a comment! Also please Subscribe to our RSS for latest tips, tricks and examples on cutting edge stuff.

Very interesting discussion glad that I came across such informative post.
Keep up the good work friend. Glad to be part of your net community. Thanks.

treelovers Treehuggers

I visited some blogsite which tacles information like this
And I got same stuff on this site http://trees360.blogspot.com/
a couple of weeks ago.

Guest

A very good article, with one bit of confusion.nnPyjamas is a port of the Google Web Toolkit (GWT), which is written in Java. nnGWT is 100K line of Java code. Pyjamas is 10K lines of Python code. nnThe author mentions webkit, which is the “engine” that the Safari and Chrome browsers are based on. nnGWT webkitn