Monday, March 26, 2012

Improved QML Simple Splitter.

The splitter from the last post works. What happens, however, if I want to add content to it, such as text boxes and other things? Well, currently I'll have to mess with the code of the splitter component itself. Obviously, I will not be able to reuse it after that, I will have to copy and paste chunks of it next time I need another splitter. This is not something I can call a good solution. So the next iteration is to somehow make it possible to reuse the splitter without making changes to its QML file, and make it possible to add content "from outside" of the component. Here comes splitter 2.0. The code itself changed very little, but the two rectangles, which are left and right panels (or top and bottom in the case of a horizontal splitter) now are not part of the component itself. To add content to panels, two properties are defined in the VerticalSplitter component.

property QtObject firstRect;
property QtObject secondRect;

These components will be assigned in the "main.qml" as follows:

//main.qml
import QtQuick 1.0

Rectangle {
width: 600
height: 600

Rectangle{
id: leftRect
color: "blue"
}

VerticalSplitter{
id: someSplitter
firstRect : leftRect
secondRect: rightRect
}

Rectangle{
id:rightRect
color: "red"
}
}

The splitter component is now simply inserted between the two panels. The panels and splitter are anchored to each other in the VerticalSplitter.qml which is almost the same as the one from the last post - probably slightly more simple. Great. I think my chunky, lousy QML is improving little by little.

//Reusable VerticalSplitter.qml
import QtQuick 1.0

Rectangle{
id: splitterRect

anchors.left: firstRect.right
anchors.right: firstRect.right
anchors.rightMargin: -10

width: 10
height: parent.height
clip: true

property QtObject firstRect;
property QtObject secondRect;

property int maximizedRect : -1;

function moveSplitterTo(x)
{
if(x > 0 && x < parent.width - splitterRect.width)
{
firstRect.width = x;
secondRect.width = parent.width - firstRect.width - splitterRect.width;
}
}

function maximizeRect(x)
{
firstRect.width = x===0 ? parent.width - splitterRect.width : 0
secondRect.width = x===0 ? 0 : parent.width - splitterRect.width
}

Component.onCompleted: {
firstRect.height = height;
firstRect.width = (firstRect.parent.width - width)/2;
firstRect.anchors.left = firstRect.parent.left;

secondRect.anchors.left = splitterRect.right;
secondRect.anchors.right = secondRect.parent.right;
secondRect.height = height;
}

onXChanged: {
moveSplitterTo(splitterRect.x);
}

BorderImage {
id: splitterBorder
anchors.fill: parent
source: "images/splitterBorder_vertical.png"
}

Image{
id: arrows
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
source: "images/splitterArrows_vertical.png"
}

MouseArea {
anchors.fill: parent
drag.axis: Drag.XAxis
drag.target: splitterRect

onClicked: {
maximizedRect = maximizedRect == 1 ? 0 : 1;
maximizeRect(maximizedRect);
}
}
}
by . Also posted on my website

No comments: