March 4, 2021
Hot Topics:

Introduction to Jython

  • By Developer.com Staff
  • Send Email »
  • More Articles »

First, a list of names is created by enclosing the names inside brackets. In Python, a list is similar to Java's ArrayList class, but with more functionality and tighter integration to the core language. This line shows one example of that integration--the ability to type new lists directly without calling functions or explicit constructors. In this example, names is set to a list containing three strings. The assignment returns no value--in Python, an assignment is a statement, not an expression. Python's list type is an example of the high-level basic types that make programming in Python so easy to manage.

The actual buttons are created from the list of names using a different Python method for creating a list called a list comprehension.

>>> buttons = [swing.JButton(each) for each in names]

The line of code can be read almost as it looks in English: "Perform the statement swing.JButton( ) once for each element in the list called names." That code creates a new JButton with each string in the list names as an argument. When evaluating a list comprehension, Python holds onto the values for each statement and returns them as a list. In this case, the variable buttons now contains a list of three JButton instances.

Now that we have a list of buttons, we can add them to the window with the use of a simple for loop.

>>> for eachButton in buttons:
...     eachButton.preferredSize = (100, 20)
...     win.contentPane.add(eachButton)
javax.swing.JButton[,0,0,0x0,invalid,layout. . .

In the interpreter, ... is used to indicate that the next line of code is part of a block--you don't actually type the dots. However, you must indent the last two lines by the same amount (at least one character) for Jython to read the block properly. The top line of this block contains a for statement. In Python, for statements work only for iterating over sequences. They are roughly the equivalent of a Java Iterator, however the loop in the Python case is executed automatically once for each element of the sequence without having to either explicitly ask the iterator for the next object or cast the object to any specific type. From the interpreter, a blank line indicates the end of a block (outside the interpreter, you'd just start the next line back at column one).

Inside the loop, the code sets the preferred size of each button and adds it to the window's content pane, again using the introspection shortcuts. Once all the buttons are added, we can pack the window again.

>>> win.pack(  )

But now, the window is a mess--the buttons are placed on top of each other, and on top of the text field. We've forgotten to give the window a layout manager (which is the mechanism Swing uses to automatically place items within a window). No problem, we can just add it after we import the appropriate package.

>>> import java.awt as awt
>>> win.contentPane.layout = awt.FlowLayout(  )
>>> win.pack(  )

Adding Behavior

At this point, the window should look right, but it doesn't do anything. We I want it to place some text in the text field depending on what button you push. First, we need to create the text we want used.

>>> quotes = {"Groucho": "Say the secret word", "Chico": "Viaduct?", "Harpo": "HONK!"}

This line sets up a Python dictionary. A dictionary in Python is more or less equivalent to a Java HashMap: a collection of key/value pairs designed to be accessed in constant time no matter which element is accessed or how large the dictionary is. Again, the Python type is well integrated with the core language, allowing the creation in one line of what would take a series of put(key, value) calls in Java.

Once the text is in place, we can define a function that will perform the actual text replacement.

>>> def buttonPressed(event):
...     field.text = quotes[event.source.text]

This pair of lines defines a function to be called when a button is pressed. The event parameter in the first line will be the actual Java Event object created from the mouseclick. The line of code inside the function uses Jython shortcuts, looks up the quotes dictionary with the text of the source button, and sets the field with that value. The Java equivalent would be something like:

field.setText(quotes.get((javax.swing.JTextField) event.getSource(  )).getText(  )))

We hope that we aren't losing credibility by suggesting that the Python example is a little bit easier to read.

Finally, we associate the function with the buttons.

>>> for eachButton in buttons:
...     eachButton.actionPerformed = buttonPressed

This for loop puts the buttonPressed function in the actionPerformed slot for each button. This is another Jython shortcut--as used in Java, buttons don't have an actionPerformed attribute. Instead, actionPerformed is the method defined inside an ActionListener interface. When you assign to actionPerformed Jython performs the appropriate call to the button's addActionListener( ) method, such that the function buttonPressed is triggered when the action is performed. Also notice that Jython allows us to use a function as the righthand side of an assignment statement, we're using the function as a value. At this point, the window should work, and look more or less like Figure 1-1.

Figure 1-1. The sample window


Of course, Jython does not have to be run interactively. The code that we used in the interactive shell session is shown as a standalone file in Example 1-1. The code is equivalent to the preceding session, but we did clean it up some, removing duplicate calls to pack( ), putting import and definitions where they would more typically come in a Python module, adding code to exit Jython when the window closes, and refactoring button creation into a separate function. Example 1-1 is typical of a Jython script as it would actually be written.

Example 1-1: The sample standalone window

import java.lang as lang
import javax.swing as swing
import java.awt as awt
names = ["Groucho", "Chico", "Harpo"]
quotes = {"Groucho": "Say the secret word", 
        "Chico": "Viaduct?", "Harpo": "HONK!"}
def buttonPressed(event):
     field.text = quotes[event.source.text]
def exit(event):
def createButton(name):
    return swing.JButton(name, preferredSize=(100,20), 
win = swing.JFrame("Welcome to Jython", size=(200, 200),windowClosing=exit)
win.contentPane.layout = awt.FlowLayout(  )
field = swing.JTextField(preferredSize=(200,20))
buttons = [createButton(each) for each in names]
for eachButton in buttons:
win.pack(  )
win.show(  )

Running this script from Jython (for example, by executing jython filename at an ordinary command prompt) will give you the same window and behavior as in Figure 1-1.

Page 2 of 4

This article was originally published on March 25, 2003

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date