I recently came across Java2Python. As I'm interested in Cairo I thought it would be interesting to try porting one of the example tutorials from ZetCode.
I'll run through the steps involved in porting then try and reach some conclusions at the end :).
1. Get setup
This is easiest in Linux, I'm running Ubuntu (in vmware), and installed
antlr 2.x
python2.5.x
sun java6
pygtk
java-gnome
You can install them like this:
# sudo apt-get install antlr python2.5 sun-java6-bin libjava-gnome-java
Then install Python2Java with easy_install
# sudo easy_install-2.5 java2python
To test if it's working run j2py -i. It should complain there is no file:
# j2py -i
Usage: j2py [options]
j2py: error: -i option requires an argument
If you get any other errors your missing some packages.
2. Get the Java Code from the Simple Example.
Save the 'simple.java' example as 'GSimple.java'
If java-gnome is running ok, compiling and running it you should see a window:
# javac GSimple.java
# java GSimple

Now we'll run through the code, it's important to understand what it
does before we port it...
##### Code Runthrough
package com.zetcode;
import org.gnome.gdk.Event;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;
/**
* ZetCode Java Gnome tutorial
*
* This program is a simple Java Gnome
* application.
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/
public class GSimple extends Window {
public GSimple() {
setTitle("Simple");
connect(new Window.DeleteEvent() {
public boolean onDeleteEvent(Widget source, Event event) {
Gtk.mainQuit();
return false;
}
});
setDefaultSize(250, 150);
setPosition(WindowPosition.CENTER);
show();
}
public static void main(String[] args) {
Gtk.init(args);
new GSimple();
Gtk.main();
}
}
- Import java-gnome bindings
- Create a class that extends org.gnome.gtk.Window
- Set the size of the window
- Connect the 'delete' event to an InnerClass. When a delete event arrives, 'onDeleteEvent' is called which in turn calls Gtk.mainQuit(). > Gtk.mainQuit() will quit program and cleanup gtk.
- set window size
- show the window #### 3. Use j2py to create the initial python code. The first stage is to generate the python.
# j2py -i GSimple.java > gsimple.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class GSimple(Window):
""" generated source for GSimple
"""
def __init__(self):
setTitle("Simple")
def onDeleteEvent(self, source, event):
Gtk.mainQuit()
return False
connect(Window.DeleteEvent())
setDefaultSize(250, 150)
setPosition(WindowPosition.CENTER)
show()
@classmethod
def main(cls, args):
Gtk.init(args)
GSimple()
Gtk.cls.main()
if __name__ == '__main__':
import sys
GSimple.main(sys.argv)
bagside@bagvapp:~/jythongnome$ python gsimple.py
Traceback (most recent call last):
File "gsimple.py", line 5, in
class GSimple(Window):
NameError: name 'Window' is not defined
self.setTitle("Simple")
def onDeleteEvent(self, source, event):
Gtk.mainQuit()
return False
self.connect(Window.DeleteEvent())
self.setDefaultSize(250, 150)
self.setPosition(WindowPosition.CENTER)
self.show()
import org.gnome.gdk.Event;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;
# To do research in the python prompt, simply start python and try
import gtk
dir(gtk)
help(gtk)
help(gtk.Window)
import gtk
help(gtk.Window)
| set_skip_taskbar_hint(...)
|
| set_startup_id(...)
|
| set_title(...)
|
| set_transient_for(...)
|
| set_type_hint(...)
|
| set_urgency_hint(...)
import gtk
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import gtk
class GSimple(gtk.Window):
""" generated source for GSimple
"""
def __init__(self):
self.setTitle("Simple")
def onDeleteEvent(self, source, event):
Gtk.mainQuit()
return False
self.connect(gtk.Window.DeleteEvent())
self.setDefaultSize(250, 150)
self.setPosition(WindowPosition.CENTER)
self.show()
@classmethod
def main(cls, args):
Gtk.init(args)
GSimple()
Gtk.cls.main()
if __name__ == '__main__':
import sys
GSimple.main(sys.argv)
Traceback (most recent call last):
File "gsimple.py", line 31, in
GSimple.main(sys.argv)
File "gsimple.py", line 25, in main
Gtk.init(args)
NameError: global name 'Gtk' is not defined
if __name__ == '__main__':
import sys
Gtk.init(args)
GSimple()
Gtk.cls.main()
[GSimple.java]
if __name__ == '__main__':
import sys
gtk.main() # Note gtk.main takes no parameters
GSimple()
# Gtk.cls.main()
# python gsimple.py
Traceback (most recent call last):
File "gsimple.py", line 30, in
GSimple()
File "gsimple.py", line 13, in __init__
self.setTitle("Simple")
AttributeError: 'GSimple' object has no attribute 'setTitle'
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import gtk
class GSimple(gtk.Window):
""" generated source for GSimple
"""
def __init__(self):
self.set_title("Simple")
def on_delete_event(self, source, event):
gtk.main_quit()
return False
self.connect(gtk.Window.DeleteEvent())
self.set_default_size(250, 150)
self.set_position(WindowPosition.CENTER)
self.show()
if __name__ == '__main__':
import sys
GSimple()
gtk.main() # Note gtk.main takes no parameters
# Gtk.cls.main()
class GSimple(gtk.Window):
""" generated source for GSimple
"""
def __init__(self):
self.set_title("Simple")
self.connect('delete_event', delete_event)
self.set_default_size(250, 150)
self.set_position(WindowPosition.CENTER)
self.show()
def delete_event(self, source, event):
gtk.main_quit()
return False
self.set_position(gtk.WIN_POS_CENTER)
Huzzah! Success!
#### Final Source code
#### Conclusions
Although Cairo APIs are available for Java and Python they are of course
quite different. One implication of this is that if you wanted to use
Cairo from a Jython java applet (via native methods) it couldn't have
code 100% the same as a normal python app.
java2python is good, but you still need to put the work in.
Working in this way is also a good way to find differences within
implementations of an API.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import gtk
class GSimple(gtk.Window):
def __init__(self):
gtk.Window.__init__(self)
self.set_title("Simple")
self.connect('delete_event', self.delete_event)
self.set_default_size(250, 150)
self.set_position(gtk.WIN_POS_CENTER)
self.show()
def delete_event(self, source, event):
gtk.main_quit()
return False
if __name__ == '__main__':
import sys
GSimple()
gtk.main()