I have been using Qt for the past few years to create UIs for various C++ applications but I haven’t tried Qt Quick and QML until now. So the thing I found really interesting about Qt Quick was that it lets you specify a UI in a declarative way (instead of imperative, as in C++) One of the things which I was wondering was if you could also specify the way graphics are drawn in a declarative way or weather it was just for the layout of ui widgets (as in the XML files produced by the Qt Designer in Qt 4.x).
After playing with it for a while I ended up with a simple QML file which draws the Koch Kurve using the HTML5 canvas.
/**
* Koch Curve
* F -> F + F - F - F + F
* F means draw a straight line, + means turn left Pi/2 and - means turn
* right Pi/2.
* See wikipedia for more.
*
* by NilsB
*/
import QtQuick 2.4
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.0
Rectangle {
width: 400
height: 600
Column {
Canvas {
id: canvas
// NOTE If I make the height and width dependent on the parent,
// then it somehow ends in an infinite loop, why?
width: 400
height: 500
antialiasing: true
property int l: 2
property int nRecursions: 1
function turnLeft(ctx) {
ctx.rotate(-Math.PI/2);
}
function turnRight(ctx) {
ctx.rotate(Math.PI/2);
}
function drawLine(ctx) {
ctx.lineTo(l, 0);
ctx.translate(l, 0);
}
function drawBasicShape(ctx) {
drawLine(ctx);
turnLeft(ctx);
drawLine(ctx);
turnRight(ctx);
drawLine(ctx);
turnRight(ctx);
drawLine(ctx);
turnLeft(ctx);
drawLine(ctx);
}
function rKoch(ctx, n) {
if (n === 1) {
drawBasicShape(ctx);
return;
}
var m = n - 1;
rKoch(ctx, m);
turnLeft(ctx);
rKoch(ctx, m);
turnRight(ctx);
rKoch(ctx, m);
turnRight(ctx);
rKoch(ctx, m);
turnLeft(ctx);
rKoch(ctx, m);
}
function kochCurve(ctx, nRecursions) {
ctx.lineWidth = 2;
ctx.strokeStyle = "darkgray";
ctx.beginPath();
ctx.translate(10, 200);
rKoch(ctx, nRecursions);
ctx.stroke();
}
onPaint: {
var ctx = canvas.getContext('2d');
ctx.reset();
kochCurve(ctx, nRecursions);
x = 0; y = 100;
}
}
Row {
Text { text: "# Recursions: " }
Slider {
id: sliderRecursions
tickmarksEnabled: true
stepSize: 1.0
minimumValue: 1
maximumValue: 6
value: 1
onValueChanged: {
canvas.nRecursions = value;
canvas.requestPaint();
}
}
}
}
}
This was easy to do by using the HMTL 5 canvas, but I kept wondering weather this is the way to do things the “QtQuick-Way” after all the canvas API is nothing Qt specific. Browsing around a bit and reading some more I figured out that there is also QQuickPaintedItem which is a wrapper around the QPainter API. So.. what is the way to paint something like a Koch Kurve in a way Qt Quick intended?
Also I ran into some problem I could not solve: For example the debugger did not show a proper stack trace when putting a breakpoint int onPaint(), but I want to see where it gets called from. And also for many JavaScript objects it just show “object” as value. So I ended up using console.log.
I also wanted to specify the size of the Canvas in terms of the size of it’s parent rectangle:
width: parent.width
height: parent.height - 100
But doing so it gets stuck in some kind of endless loop where onPaint(..) gets called all the time. I could not figure out why and from where using the debugger.
One more thing I also could not figure out is weather I have to use JavaScript or I can just use QML and C++ for all the non-declarative code.
↧









