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.
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.
2 Responses to “Qt Jambi a door opener”
How to define slot in JRuby?
Hi, I had a look at JRuby last night. And it looks to me that your problem is that methods defined in JRuby are not visible to Java’s reflection api. I know that there has been suggested a workaround for this on the Qt Jambi mailing list for Jython.
http://lists.trolltech.com/qt-jambi-interest/2007-03/thread00053-0.html
Maybe that thread could lead to a solution for you. ![]()
