Back to Blog home

Qt Jambi a door opener

Published on Friday June 08, 2007 by haavardf in Qt Qt Jambi | Comments

Qt Jambi is a new product that will let Java programmer harvest the power of Qt. Now it turns out that it's not only Java addicts that should get excited. There are a bunch of languages that compiles to byte code, and are using the existing JVM as it's runtime. I set out to investigate the possibilities, and it is looking good :-)

Let's start by looking at Kawa . Kawa is an implementation of Scheme, which is in the Lisp family of programming languages. So let's try to open a file dialog, and connect it's signal currentChanged to println. To run the code below, just make sure kawa is in your path, and that the the qtjambi.jar is in the classpath.

#!/usr/bin/env kawa.sh

(invoke-static <com.trolltech.qt.gui.QApplication> 'initialize (<java.lang.String[]>))

(set! fileDialog (make <com.trolltech.qt.gui.QFileDialog>))
(*:show fileDialog)

(*:connect (*:.currentChanged fileDialog)
(<java.lang.System>:.out) "println(String)")

(invoke-static <com.trolltech.qt.gui.QApplication> 'exec )

Hey, that worked just perfect. It opened a file dialog, and printed out the name of the selected file to the console.

Ok, let's have a look at Groovy. We will try to do something a bit more complicated this time. Let's make an interactive graph plotter.

groovy-1.png

import com.trolltech.qt.core.*
import com.trolltech.qt.gui.*

class FunctionPlotter extends QWidget {
FunctionPlotter(parent) {
super(parent)
}

def function

def protected void paintEvent(QPaintEvent e) {
QPainter painter = new QPainter(this);
painter.translate((int)(width()/2), (int)(height()/2))
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
painter.setPen(QColor.blue)
painter.drawLine((int)(-width()/2), 0, (int)(width()/2), 0)
painter.drawLine(0, (int)(-height()/2), 0, (int)(height()/2))
painter.setPen(QColor.black)

double y;
double x = -width()/2;
while (x < width()/2) {

try {
y = function(x)
painter.drawPoint((int)x, (int)-y)
}
catch(exeption){}

x++;
}
painter.end()
}

def public void eval(String s) {
System.out.println("Eval: " + s);
def shell = new GroovyShell()
try{
function = shell.evaluate("{x -> " + s + "}")
update()
}
catch(e){}
}

def protected QSize sizeHint() {
new QSize(500, 400)
}
}

class Fun extends QWidget {

def input = new QLineEdit(this)
def plotter = new FunctionPlotter(this)

Fun(parent) {
super(parent)
def QVBoxLayout layout = new QVBoxLayout()
layout.addWidget(input)
input.setText("Math.cos(x / 50) * 300")
plotter.eval(input.text())
layout.addWidget(plotter)
setLayout(layout)
input.textEdited.connect(plotter, "eval(String)")
}
}

QApplication.initialize( this.args )

def fun = new Fun(null)
fun.show();

QApplication.exec();

That was fun :-), so what did we do. We created a widget (Fun) with a QLineEdit and a custom FunctionPlotter widget. Then we connected the QLineEdit's input to the FunctionPlotters eval function. The FunctionPlotters eval function would try to evaluate the expression, and assign the resulting function to the function variable. Each time the widget needs to paint the graph, it will call this function for each x value that fit's on the plot, and plot a dot for the result.

This approach is of course fairly unsafe, since you could write a function that formated your harddrive, but it also shows some of the power of a scriptable language.

Good luck with exploring the possibilities, and post a comment when you have tried some other languages.

Subscribe to Our Blog

Stay up to date with the latest marketing, sales and service tips and news.