Using Java2Python to port a JavaCairo tutorial
Posted by stu at August 21st, 2009
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…
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();
}
}
Code Runthrough
- 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
Output [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)
5. Analyze
Unfortunately j2py is not magic, it’s time to have a look at the code..
Things are missing and others look wrong, heres an initial list of problems:
- no imports
- ‘self’ not specified in class constructor
- CamelCase used – this is suspicious, it’s unlikely the cairo bindings work like this
- @classmethod is probably not nessacary here
- Gtk.cls.main() – This looks particularly suspicious
Indeed – If you try and run it, the missing imports become apparent:
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
6. Fixing the initial Problems
Some problems are easy to fix, others involve learning the differences between the java and python APIs.
Starting with the easiest…
‘self’ not specified in class constructor
This looks easiest so we’ll tackle it first, heres the new constructor:
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()
Doing this does emphasize how wrong the CamelCase looks, also the onDeleteEvent being a function in the constructor doesn’t look right, we could probably move it up a level.
No imports
In the java code there is
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;
Googling for Window module and gtk you’ll end up at the pygtk site.
The documentation shows the Window class is in the gtk module. Further research on the site or in the python prompt shows most of the other classes are in the same module too.
# To do research in the python prompt, simply start python and try import gtk dir(gtk) help(gtk) help(gtk.Window)
It’s worth having a glance at the python help to see if the bindings look the same, start python and try:
import gtk help(gtk.Window)
…[output snipped]…
| set_skip_taskbar_hint(...) | | set_startup_id(...) | | set_title(...) | | set_transient_for(...) | | set_type_hint(...) | | set_urgency_hint(...)
It’s fairly obvious that CamelCase is not used here, as suspected (remember to change this later…)
As “Window” is quite generic, I’ll move everything into the ‘gtk’ namespace, add
import gtk
To the top of the code, and change all instances of the gtk classes to ‘gtk.ClassName’, e.g. gtk.Window:
#!/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)
And try running it:
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
It’s complaining about the ‘main’ class method on GSimple, we can just remove it and move everything into the main method of the module:
if __name__ == '__main__':
import sys
Gtk.init(args)
GSimple()
Gtk.cls.main()
This still won’t work for sure as ‘Gtk’ is not in the namespace.
The first step is to work out whats going on, consult the java code then the relevant documentation.
[GSimple.java]public static void main(String[] args) {
Gtk.init(args);
new GSimple();
Gtk.main();
}
OK, the code is the same, what does the java gnome documentation say about Gtk.init ?
init
public static void init(String[] args)
Initialize the GTK libraries. This must be called before any other org.gnome.* classes are used.
Parameters:
args – The command line arguments array. This is passed to the underlying library to allowing user (or window manager) to alter GTK’s behaviour.
Since:
4.0.0
Looking in pygtk there isn’t ‘init’ (it would be confusing having this and __init__ anyway).
Looking in the pygtk documentation there is no ‘init’ method (which makes sense as it could be confused with ‘__init__’. There is however gtk.main:
gtk.main
def gtk.main()
The gtk.main() function runs the main loop until the gtk.main_quit() function is called. You can nest calls to gtk.main(). In that case the call to the gtk.main_quit() function will make the innermost invocation of the main loop return.
Here I confess some prior knowledge, I already had a vague idea the main loop might be involved as I’d worked with gtk before.
So we’ll try gtk.main, and commenting out the line calling main on the class as I’m not entirely sure what it does:
if __name__ == '__main__':
import sys
gtk.main() # Note gtk.main takes no parameters
GSimple()
# Gtk.cls.main()
Try running
And… nothing happens – you have to quit with CTRL-C!
It looks like it’s not even getting to the constructor (as there should be errors here, maybe gtk.main() needs to run *after* the GSimple() constructor..
Sure enough:
# 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'
Fixing the CamelCase
The pygtk documentation seemed all be underscored_lowercase, it’s probably safe to speculatively change everything to this then fix any errors:
#!/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()
Output:
python gsimple.py
gsimple.py:12: GtkWarning: gtk_window_set_title: assertion `GTK_IS_WINDOW (window)' failed
self.set_title("Simple")
Traceback (most recent call last):
File "gsimple.py", line 28, in
GSimple()
File "gsimple.py", line 18, in __init__
self.connect(gtk.Window.DeleteEvent())
AttributeError: type object 'gtk.Window' has no attribute 'DeleteEvent'
Thats progress! It means the self.set_title call probably works, and there is a self.connect call too.
There is no DeleteEvent in the pygtk documentation… which is not suprising as it looks more java than python.
Better to step back and have a look at self.connect, in the end I googled
gtk connect delete event
And got to a getting started with pygtk page:
36 # When the window is given the "delete_event" signal (this is given
37 # by the window manager, usually by the "close" option, or on the
38 # titlebar), we ask it to call the delete_event () function
39 # as defined above. The data passed to the callback
40 # function is NULL and is ignored in the callback function.
41 self.window.connect("delete_event", self.delete_event)
Note here they have ‘window’ as their delegating, our generated code extends this class.
The signature is slightly different, also instead of ‘on_delete_event’ the function is just called ‘delete_event’, this seems more pythonic so we’ll do the same.
This would also be a good time to move the function into the main class, out of the constructor:
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
And the output:
gsimple.py:12: GtkWarning: gtk_window_set_title: assertion `GTK_IS_WINDOW (window)' failed
self.set_title("Simple")
Traceback (most recent call last):
File "gsimple.py", line 29, in
GSimple()
File "gsimple.py", line 14, in __init__
self.connect('delete_event', delete_event)
NameError: global name 'delete_event' is not defined
The first line assertion `GTK_IS_WINDOW (window)’ failed is the important one here; it makes sense, the constructor of the gtk.Window has not been called yet.
Add
gtk.Window.__init__(self)
to the top of the constructor and run.
Traceback (most recent call last): File "gsimple.py", line 30, inGSimple() File "gsimple.py", line 17, in __init__ self.set_position(WindowPosition.CENTER) NameError: global name 'WindowPosition' is not defined
And again…
Repeating the same process for WindowPosition and set_position, you’ll find that the set_position line should look like this:
self.set_position(gtk.WIN_POS_CENTER)
And the output…

Huzzah! Success!
Final Source code
#!/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()
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.
Commentary
Trackbacks
Leave a comment, a trackback from your own site or subscribe to an RSS feed for this entry.

Hi,
After follow all steps with succes, I have a problem at the moment to execute this command
$ j2py -i
I get this:
Traceback (most recent call last):
File “/usr/local/bin/j2py”, line 9, in
from java2python.lib.lexer import Lexer
File “/usr/local/lib/python2.6/dist-packages/java2python/lib/lexer.py”, line 4, in
import antlr
ImportError: No module named antlr
I have antlr installed, so what else can I do?
Thanks for help.
Oscar
Well, problem solved, it’s maybe a conflict with python 2.6.x and 2.5.x,
I installed antlr 2.7.x from synaptic and all is done.
Oscar
Cool, I thought I was the only one crazy to try this
Keep us posted if you do anything with gtk and jython !
stu
Hi again, this was helpful, I’m trying to convert java regex into python re, just for a homework, but this is a good tool, I’d do the example but when I type this command ‘$ javac GSimple.java’ show a lot of compilation bugs. In some aplications the .py file shows and and exception with character ‘@’, maybe cannot handle actions commands with interface like ‘@Action’.
Well i’ll show what I’d do for installation:
1. $ sudo apt-get install antlr python2.5 sun-java6-bin libjava-gnome-java
2. $ sudo easy_install-2.5 java2python Don’t work at the beggining but I tried with:
$ sudo apt-get install python-setuptools and again with 2.
3. But the command $ j2py -i don’t work, and then run $ antlr, the system show me try with ‘apt-get install pccts’ I’d do and try again with j2py -i, but nothing.
4. $ sudo synaptic, then search and check all antlr 2.7.7 related packages and then all works without problems.
Oscar
Oops I forgot that, maybe the ‘python-antlr’ package found in synaptic fix my problem.
Pd: sorry for my bad english (just in case)
Oscar
Cool, so python-antlr fixed it ?
If your having trouble compiling GSimple.java it could be a problem with java-gnome, post the errors here if it’s not working.
I should probably update the article to python 2.6 at some point.
stu
Hi again,
there are my errors:
javac Gsimple.java
Gsimple.java:21: class GSimple is public, should be declared in a file named GSimple.java
public class GSimple extends Window {
^
Gsimple.java:3: package org.gnome.gdk does not exist
import org.gnome.gdk.Event;
^
Gsimple.java:4: package org.gnome.gtk does not exist
import org.gnome.gtk.Gtk;
^
Gsimple.java:5: package org.gnome.gtk does not exist
import org.gnome.gtk.Widget;
^
Gsimple.java:6: package org.gnome.gtk does not exist
import org.gnome.gtk.Window;
^
Gsimple.java:7: package org.gnome.gtk does not exist
import org.gnome.gtk.WindowPosition;
^
Gsimple.java:21: cannot find symbol
symbol: class Window
public class GSimple extends Window {
^
Gsimple.java:25: cannot find symbol
symbol : method setTitle(java.lang.String)
location: class com.zetcode.GSimple
setTitle(“Simple”);
^
Gsimple.java:27: package Window does not exist
connect(new Window.DeleteEvent() {
^
Gsimple.java:34: cannot find symbol
symbol : method setDefaultSize(int,int)
location: class com.zetcode.GSimple
setDefaultSize(250, 150);
^
Gsimple.java:35: cannot find symbol
symbol : variable WindowPosition
location: class com.zetcode.GSimple
setPosition(WindowPosition.CENTER);
^
Gsimple.java:36: cannot find symbol
symbol : method show()
location: class com.zetcode.GSimple
show();
^
Gsimple.java:40: cannot find symbol
symbol : variable Gtk
location: class com.zetcode.GSimple
Gtk.init(args);
^
Gsimple.java:42: cannot find symbol
symbol : variable Gtk
location: class com.zetcode.GSimple
Gtk.main();
^
14 errors
I have Xubuntu 9.10 and I installed the libjava-gnome-java package.
which more dependencies I need?
Oscar
Hi,
The first problem is because the file is called Gsimple.java, not GSimple.java (notice the second ‘s’ should be uppercase).
The other errors look like java gnome is not in the classpath.
stu
I had a bit of a go at this on the weekend.
The current version of the java-gnome bindings is 4.x, for a while ubuntu had the old bindings installed (my test vm seems to).
To check which version you have look in
/usr/share/java
gtk-4.0.jar Is the correct version
gtk2.10 Is the old version
I managed dist-upgrade my ubuntu to karmic koala, but
$ sudo apt-get upgrade libjava-gnome-java
Was still not enough… however:
$ sudo apt-get remove libjava-gnome-java
$ sudo apt-get install libjava-gnome-java
DID install gtk-4.0.jar.
You may need to manually set the classpath:
$ export CLASSPATH=/usr/share/java/gtk-4.0.jar
Unfortunately I don’t have the vm I used to write this tutorial with at the moment, so it’s a little tricky to test stuff – if I get time I’ll try and get everything working again and fix any gaps in the tutorial.
stu