Build a Paint Application for Tablet

This article gives an overview of how a basic paint app can be built using QML, QDeclarativeView targeted for MeeGo*. QML is a JavaScript*-like language which gives a rich user interface for your application. You can find more information about the same here: http://wiki.meego.com/QML_tutorials

Paint App

The Idea

The idea here is to dynamically create a QML element using JavaScript* and embed the same into the root element at a given set of (x,y) coordinates. The (x,y) coordinates here can be obtained from the mouse location. This in the case of a tablet will be your finger location on the screen. The root element which can be a "rectangle" will act as a "canvas" on which you can draw shapes.

We will also add features like color selection, size selection - width of the pen for your drawing.

Basic Setup

MeeGo* SDK for Windows* is being used to develop this application. Installation and setup instructions can be found in the “Quick Reference” section of this article. Qt* Creator, the IDE that comes with MeeGo* SDK, is being used to develop this sample. On a Windows* 7 machine, here are the steps that will allow you to create this app.

"Start" > All Programs > Meego 1.2 SDK > QtCreator

In the QtCreator click on File > New File or Project > Select "Mobile Qt Application" from the list, follow the wizard and create a Project.

You can choose a target here. Instructions on how to set up these targets can be found in the “Quick Reference” section of this article.

We now need to make some updates to the project to use QML for the UI:

delete "mainwindow.ui" from the project list

In mainwindow.cpp remove

#include "ui_mainwindow.h"

update the constructor from

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
     ui->setupUi(this);
}

to

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
}

From the File menu select "New File or Project" and from the listing under "Files and Classes" select "QML" on the right hand side, select "QML File", select a file name, and click Finish.

Once the Qml File is added, we need to add the same to the project resources. From the File menu select "New File or Project" and from the listing under "Files and Classes" select "Qt", on the right hand side select "Qt Resource File", select a file name, and click Finish.

Double click on the resource file and add a prefix and the file. I used "/" for my prefix and added "ui.qml".

We will use QDeclarativeView and set the source of the QDeclarativeView to our QML file. To do this we will edit the MainWindow class. But before doing that, we need to make QDeclarative library visible to the project. This can be done by editing the "QMLPaintApp.pro" file and updating the following line:

QT       += core gui declarative 

Now edit the MainWindow.h and then MainWindow.cpp

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtDeclarative/QDeclarativeView>
namespace Ui {
    class MainWindow;
}
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
private:
    QDeclarativeView *ui;
};
#endif // MAINWINDOW_H

Add QDeclarativeView *ui as a member variable to the MainWindow class. To get QdeclarativeView support, <QtDeclarative/QDeclarativeView> is needed in the includes section.

MainWindow.cpp

#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
  ui = new QDeclarativeView;
  ui->setSource(QUrl("qrc:/ui.qml"));
  ui->setResizeMode(QDeclarativeView::SizeRootObjectToView);
  setCentralWidget(ui);
}
MainWindow::~MainWindow()
{
    delete ui;
}

In the constructor of MainWindow class, instantiate the QDeclarativeView item and set the source to the QML file.

ui->setSource(QUrl("qrc:/ui.qml"));

"qrc:/ui.qml" // qt resource file location

In the QML file we will now create a drawing canvas item. This will be a rectangle("rect") of size 640 X 480.

import Qt 4.7
Rectangle {
    id: rect
    width: 640
    height: 480
}

To capture the mouse event on this canvas “rect” we need to add mousearea and capture the event “OnMousePositionChanged”. This event will be fired whenever the mouse changes its position.

MouseArea{
                   anchors.fill:parent
                   focus:true
                   onMousePositionChanged:
                    {
                    }
               }

We have the mouse event and we need to wire this up to a JavaScript* callback function. We will use an external JavaScript* file which will have the callback function.

Right click on the project. In the “General” section select “Text File” and name it functions.js.

Add this JavaScript* file to the resources following the procedure explained above(same as how we added ui.qml).

In the Qml file, import the same and give an alias to functions.js.

import "functions.js" as PaintFunctions

In the JavaScript* file we need to now have a callback function.

var color = 'black'; // color of the pen, here the dynamic rectangle
var width = 50; // width of the pen
var height = 50;/ height of the pen

function paintshape(x,y)
{
   var object = Qt.createQmlObject('import Qt 4.7; Rectangle {id: indrect; width:'+width+'; height:'+height+'; color: "'+color+'"; }',
           rect, "dynamicSnippet"+x); // create a rectangle on the fly
      object.x = x; // set it at a perticular location on the screen
      object.y = y;
}

The paintshape will take x,y coordinates of the mouse position and at that given location will add in a dynamic QML element.

Qt.createQmlObject creates an element dynamically and object.x = x; object.y = y; sets the object at the given coordinates. The size and color of the element are declared as global variables in order to make them more dynamic. This will later on help us with changing the color and size of these dynamic rectangles. As of now we will set the color to “black” and the size to “50 X 50”.

We just need to add this callback function to “onMousePositionChanged” event and pass the mouse location.

import Qt 4.7
import "functions.js" as PaintFunctions
Rectangle {
    width: 640
    height: 480
    id: rect
    MouseArea{
        anchors.fill:parent
        focus:true
        onMousePositionChanged:
         {
            PaintFunctions.paintshape(mouseX,mouseY);  // callback function call to the mouse position change event     
        }
    }
}

We will now add dynamic color and size selection. As this is targeted to a touch-based device, a tablet, we will use a gesture to capture the color selection. For this we will again use rectangles as buttons. When a "green" rectangle of size "50X50" is tapped, the pen color will change to "green" and size is set to "50X50".

Using GestureArea we will listen to “onTapAndHold” event. When the event gets fired, a callback function “setcolorSize” will be called that updates the global variables (color, height, width) to the selected color and size.

import Qt 4.7
import Qt.labs.gestures 1.0
import "functions.js" as PaintFunctions
Rectangle{
    width:700; height:500;
    Rectangle{
        width:700; height:5; id:toprect
    }
    Item {
        width: 700; height: 500; anchors.topMargin: 20;anchors.top : toprect.bottom;
          Rectangle {
              width:500; height:100;
              id:colorselect;
              Grid {
                  anchors.horizontalCenter: parent.horizontalCenter
                  columns:9
                  spacing: 5
                  Rectangle { color: "blue";
                      width: 50; height: 50; border.color:"gray"; border.width:2;radius: 20.0;
                      GestureArea{ anchors.fill:parent; focus: true; onTapAndHold:{ PaintFunctions.setcolorSize("blue",50,50);}}
                  }
                  Rectangle { color: "yellow";
                      width: 50; height: 50; border.color:"gray"; border.width:2;radius: 20.0;
                      GestureArea{ anchors.fill:parent; focus: true; onTapAndHold:{ PaintFunctions.setcolorSize("yellow",50,50);}}
                  }
                  Rectangle { color: "green";
                      width: 50; height: 50; border.color:"gray"; border.width:2;radius: 20.0;
                       // callback for tap and hold
                      GestureArea{ anchors.fill:parent; focus: true; onTapAndHold:{ PaintFunctions.setcolorSize("green",50,50);}} 
                  }
              }
        }
          Rectangle {
                   id: rect
                   width: 640
                   height: 480
                   anchors.top:colorselect.bottom
                   anchors.topMargin: 5
               MouseArea{
                   anchors.fill:parent
                   focus:true
                   onMousePositionChanged:
                    {
                       PaintFunctions.paintshape(mouseX,mouseY); 
                   }
               }
    }
 }
}

var color = 'black'; 
var width = 50;
var height = 50;

function setcolorSize(c,w,h) {
    color = c; // update the color
    width = w; //update the width    
    height = h; //update the height
}

function paintshape(x,y)
{
   var object = Qt.createQmlObject('import Qt 4.7; Rectangle {id: indrect; width:'+width+'; height:'+height+'; color: "'+color+'"; }',
           rect, "dynamicSnippet"+x);
      object.x = x;
      object.y = y;
}

That's it! You have a paint application. You can change the color and size of the pen. Happy painting!

Quick References


4.875
Average: 4.9 (8 votes)

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Posted On : April 27, 2011 - 08:55
rzr
Offline
Last seen: 5 days 19 hours ago
 Brown Belt
Joined: Feb 18 2011
Points: 1027

can you publish a tarball of the sources too ?
--
http://rzr.online.fr/q/qt

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.