×
Namespaces

Variants
Actions
(Difference between revisions)

Creating Compass in Qt and Windows Phone

From Nokia Developer Wiki
Jump to: navigation, search
hamishwillee (Talk | contribs)
m (Hamishwillee - Minor tidy)
croozeus (Talk | contribs)
m (Croozeus - - Qt Project (MainPage.qml): code tagged javascript)
(8 intermediate revisions by 2 users not shown)
Line 1: Line 1:
[[Category:Windows Phone]][[Category:Qt Quick]][[Category:Code Examples]][[Category:Porting]][[Category:Location]]
+
[[Category:Windows Phone]][[Category:Qt Quick]][[Category:Code Examples]][[Category:Porting]][[Category:Location]][[Category:Sensor]][[Category:UI]]
{{Abstract|This article demonstrates how to create a Compass in Qt and WP7.}}
+
{{Abstract|This article demonstrates how to create a Compass in Qt and WP7.}}
{{ArticleMetaData
+
{{ArticleMetaData <!-- v1.2 -->
|sourcecode= [[Media: CompassQML_v1.1.zip]] [[Media: CompassWp7.zip]]<!-- Link to example source code e.g. [[Media:The Code Example ZIP.zip]] -->
+
|sourcecode= [[Media:CompassWp7.zip]] [[Media:CompassQML v1.3.zip]]  
 
|installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.sis]]) -->
 
|installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.sis]]) -->
 
|devices= N8 (Nokia Belle), Windows Phone  <!-- Devices tested against - e.g. ''devices=N95, N8'') -->
 
|devices= N8 (Nokia Belle), Windows Phone  <!-- Devices tested against - e.g. ''devices=N95, N8'') -->
 
|sdk= [http://www.developer.nokia.com/Develop/Windows_Phone/Tools/ Windows Phone SDK 7.1], Qt SDK v1.2
 
|sdk= [http://www.developer.nokia.com/Develop/Windows_Phone/Tools/ Windows Phone SDK 7.1], Qt SDK v1.2
 
|platform= WP7.1, Symbian^3
 
|platform= WP7.1, Symbian^3
|devicecompatability= All with compass sensors in platform
+
|devicecompatability= All with compass sensors in platform
 +
|dependencies= <!-- Any other/external dependencies e.g.: Google Maps Api v1.0 -->
 
|signing= Self-Signed <!-- Signing requirements - empty or one of: Self-Signed, DevCert, Manufacturer -->
 
|signing= Self-Signed <!-- Signing requirements - empty or one of: Self-Signed, DevCert, Manufacturer -->
 
|capabilities= sensors <!-- Capabilities required by the article/code example (e.g. Location, NetworkServices. -->
 
|capabilities= sensors <!-- Capabilities required by the article/code example (e.g. Location, NetworkServices. -->
 
|keywords= Compass, Sensors
 
|keywords= Compass, Sensors
 +
|language= <!-- Language category code for non-English topics - e.g. Lang-Chinese -->
 +
|translated-by= <!-- [[User:XXXX]] -->
 +
|translated-from-title= <!-- Title only -->
 +
|translated-from-id= <!-- Id of translated revision -->
 +
|review-by= <!-- After re-review: [[User:username]] -->
 +
|review-timestamp= <!-- After re-review: YYYYMMDD -->
 +
|update-by= <!-- After significant update: [[User:username]]-->
 +
|update-timestamp= <!-- After significant update: YYYYMMDD -->
 
|creationdate= 20120416
 
|creationdate= 20120416
 
|author= [[User:somnathbanik]]
 
|author= [[User:somnathbanik]]
 
}}
 
}}
 
==Introduction==
 
==Introduction==
In this article we will create a Compass in QML using [http://doc.qt.nokia.com/qtmobility-1.2/qml-compass.html QML Compass Element] which is a part of  [http://doc.qt.nokia.com/qtmobility-1.2/index.html QtMobility 1.x] and for WP7 we will use [http://msdn.microsoft.com/en-us/library/microsoft.maps.mapcontrol.navigation.compass.aspx#feedback Compass Class].  This is a magnetic compass used to determine the direction of the earth's magnetic north pole.
+
In this article we will create a Compass in QML using [http://doc.qt.nokia.com/qtmobility-1.2/qml-compass.html QML Compass Element] which is a part of  [http://doc.qt.nokia.com/qtmobility-1.2/index.html QtMobility 1.x] and for WP7 we will use [http://msdn.microsoft.com/en-us/library/microsoft.maps.mapcontrol.navigation.compass.aspx#feedback Compass Class].  This is a magnetic compass used to determine the direction of the earth's magnetic north pole.
  
 
[[File: CompassQML.png|thumb|none|201px|Compass using QML ]]
 
[[File: CompassQML.png|thumb|none|201px|Compass using QML ]]
Line 23: Line 32:
  
 
===Qt Project (MainPage.qml)===
 
===Qt Project (MainPage.qml)===
Let’s first create a circle using [http://doc.qt.nokia.com/4.7/qml-rectangle.html Rectangle] Element as shown in the above figure. This circle will determine the compass outline. In QML [http://doc.qt.nokia.com/4.7/qml-rectangle.html Rectangle] can be used to draw a circle with 1:1 dimensions and a radius.
+
Let’s first create a circle using [http://doc.qt.nokia.com/4.7/qml-rectangle.html Rectangle] Element as shown in the above figure. This circle will determine the compass outline. In QML [http://doc.qt.nokia.com/4.7/qml-rectangle.html Rectangle] can be used to draw a circle with 1:1 dimensions and a radius.
 
<code css>
 
<code css>
Rectangle
+
Rectangle
    {
+
{
    id:circle
+
id:circle
    width: 250
+
width: 250
    height: 250
+
height: 250
    color: "transparent"
+
color: "transparent"
    border.color: "green"
+
border.color: "green"
    border.width: 3
+
border.width: 3
    radius: width*0.5
+
radius: width*0.5
    anchors.centerIn: parent
+
anchors.centerIn: parent
    }
+
}
 
</code>
 
</code>
We add an [http://doc.qt.nokia.com/4.7/qml-image.html Image] to create the compass needle and rotate the [http://doc.qt.nokia.com/4.7/qml-image.html Image] with its change in degrees (angle).
+
We add an [http://doc.qt.nokia.com/4.7/qml-image.html Image] to create the compass needle and rotate the [http://doc.qt.nokia.com/4.7/qml-image.html Image] with its change in degrees (angle).
<code css>
+
<code javascript>
 
  Image {
 
  Image {
        id: arrowImage
+
id: arrowImage
        anchors.bottom: circle.verticalCenter
+
anchors.bottom: circle.verticalCenter
        anchors.horizontalCenter: circle.horizontalCenter
+
anchors.horizontalCenter: circle.horizontalCenter
        height: circle.paintedHeight / 2
+
height: circle.paintedHeight / 2
        fillMode: Image.PreserveAspectFit
+
fillMode: Image.PreserveAspectFit
        source: "upload.png"
+
source: "upload.png"
        rotation: -needleRotation
+
rotation: -needleRotation
        transformOrigin: Item.Bottom
+
transformOrigin: Item.Bottom
    }
+
}
 
</code>   
 
</code>   
 
[http://doc.qt.nokia.com/qtmobility-1.2/qml-compass.html QML Compass Element] is used to get the change in magnetic north reading in the {{Icode|Compass}}.  
 
[http://doc.qt.nokia.com/qtmobility-1.2/qml-compass.html QML Compass Element] is used to get the change in magnetic north reading in the {{Icode|Compass}}.  
<code css>
+
<code javascript>
 
  Compass {
 
  Compass {
        id: compass
+
id: compass
        active: true
+
active: true
        onReadingChanged: {
+
onReadingChanged: {
            timerCompassCheck.compassActivated = true; //notify timer that Compass is working
+
  timerCompassCheck.running= false; //disable timer because Compass is working
            mainPage.needleRotation = reading.azimuth;
+
  mainPage.needleRotation = reading.azimuth;
        }
+
}
    }
+
}
 
</code>
 
</code>
 
We also set a [http://doc.qt.nokia.com/4.7/qml-timer.html Timer] which expires after 7 seconds to check whether the compass is working properly (for example, it may not be supported on the device).
 
We also set a [http://doc.qt.nokia.com/4.7/qml-timer.html Timer] which expires after 7 seconds to check whether the compass is working properly (for example, it may not be supported on the device).
<code css>
+
<code javascript>
 
Timer {
 
Timer {
                id: timerCompassCheck
+
id: timerCompassCheck
                property bool compassActivated: false
+
running: true
                running: true
+
repeat: false
                interval: 7000
+
interval: 7000
                onTriggered: {
+
onTriggered: {
                    if (!compassActivated) {
+
compassTextError.visible=true;
                        // check compass response in 7 seconds.
+
  }
                        compassTextError.visible=true;
+
}
                        running = false;
+
                    }
+
              }
+
      }
+
 
</code>
 
</code>
The {{Icode|onReadingChanged}} signal of the [http://doc.qt.nokia.com/qtmobility-1.2/qml-compass.html Compass Element] first set the {{Icode|compassActivated}} property of [http://doc.qt.nokia.com/4.7/qml-timer.html Timer Elementto ''true'' to ensure that device has compass supports, or else a message is displayed that device doesn't support compass. Also the signal {{Icode|onReadingChanged}} of the [http://doc.qt.nokia.com/qtmobility-1.2/qml-compass.html Compass Element] gets the compass reading and set it to {{Icode|needleRotation }} property which then used to rotate the compass needle angle.
+
As soon as the application launches the [http://doc.qt.nokia.com/4.7/qml-timer.html Timer ] starts running  and expires after 7 seconds, the [http://doc.qt.nokia.com/4.7/qml-timer.html Timer ]  doesn't repeat as the ''repeat'' property is set to false. When the {{Icode|onReadingChanged}} signal of the [http://doc.qt.nokia.com/qtmobility-1.2/qml-compass.html Compass Element] is called it first stops the [http://doc.qt.nokia.com/4.7/qml-timer.html Timer ] and  gets the compass reading and set it to {{Icode|needleRotation }} property which then used to rotate the compass needle angle. If within 7 seconds the signal {{Icode|onReadingChanged}} of the [http://doc.qt.nokia.com/qtmobility-1.2/qml-compass.html Compass Element]  is not called, then the [http://doc.qt.nokia.com/4.7/qml-timer.html Timer ] expires and displays a message that the device doesn't support compass.
 
+
A [http://doc.qt.nokia.com/4.7/qml-text.html Text] element is being added to display the magnetic north value of the compass change on the device screen.  
A [http://doc.qt.nokia.com/4.7/qml-text.html Text] element is being added to display the magnetic north value of the compass change on the device screen.  
+
<code javascript>
<code css>
+
 
Text {
 
Text {
 
         id:needleRotationText
 
         id:needleRotationText
Line 94: Line 98:
  
 
=== WP7 Project (MainPage.xaml)===
 
=== WP7 Project (MainPage.xaml)===
To build a similar interface like Qt, let’s first create a circle using [http://msdn.microsoft.com/en-us/library/system.windows.shapes.ellipse.aspx Ellipse Class] which defines the outline of the compass.
+
To build a similar interface like Qt, let’s first create a circle using [http://msdn.microsoft.com/en-us/library/system.windows.shapes.ellipse.aspx Ellipse Class] which defines the outline of the compass.
 
<code xml>
 
<code xml>
 
<Ellipse StrokeThickness="2" x:Name="circle" Width="400" Height="400"  
 
<Ellipse StrokeThickness="2" x:Name="circle" Width="400" Height="400"  
Line 105: Line 109:
 
To create the compass needle we used [http://msdn.microsoft.com/en-us/library/system.windows.shapes.line.aspx Line Class].
 
To create the compass needle we used [http://msdn.microsoft.com/en-us/library/system.windows.shapes.line.aspx Line Class].
 
<code xml>
 
<code xml>
<Line x:Name="line" X1="240" Y1="350" X2="240" Y2="270"  Stroke="{StaticResource PhoneForegroundBrush}" StrokeThickness="4"></Line>
+
<Line x:Name="line" X1="240" Y1="350" X2="240" Y2="270"  Stroke="{StaticResource PhoneForegroundBrush}" StrokeThickness="4"></Line>
 
</code>
 
</code>
Now we add the reference {{Icode|Microsoft.Devices.Sensors}}  to initialize and detect the compass presence in the device.
+
Now we add the reference {{Icode|Microsoft.Devices.Sensors}}  to initialize and detect the compass presence in the device.
<code cpp>
+
<code cpp-qt>
 
Compass compass;  
 
Compass compass;  
 
if (Compass.IsSupported)
 
if (Compass.IsSupported)
Line 122: Line 126:
 
             }
 
             }
 
</code>
 
</code>
{{Icode|TimeBetweenUpdates}}  property will update the compass data in every second.  {{Icode|CurrentValueChanged}} event handler will give the compass value each time there is any change in the compass needle position.  And then we call the {{Icode|Start()}} method to start the compass. The change in compass value is then passed to the {{Icode|compass_CurrentValueChanged()}} method. Which then pass to a separate thread using {{Icode|Dispatcher.BeginInvoke()}} method.
+
{{Icode|TimeBetweenUpdates}}  property will update the compass data in every second.  {{Icode|CurrentValueChanged}} event handler will give the compass value each time there is any change in the compass needle position.  And then we call the {{Icode|Start()}} method to start the compass. The change in compass value is then passed to the {{Icode|compass_CurrentValueChanged()}} method. Which then pass to a separate thread using {{Icode|Dispatcher.BeginInvoke()}} method.
<code cpp>
+
<code cpp-qt>
 
void compass_CurrentValueChanged(object sender, SensorReadingEventArgs<CompassReading> e)
 
void compass_CurrentValueChanged(object sender, SensorReadingEventArgs<CompassReading> e)
 
         {
 
         {
Line 130: Line 134:
 
</code>
 
</code>
  
<code cpp>
+
<code cpp-qt>
 
private void UpdateLine(CompassReading e)
 
private void UpdateLine(CompassReading e)
 
         {
 
         {
Line 138: Line 142:
 
         }
 
         }
 
</code>
 
</code>
The {{Icode|MagneticHeading}}  gives the magnetic north pole value of the compass and is displayed in a [http://msdn.microsoft.com/en-us/library/system.windows.controls.textblock%28v=VS.95%29.aspx TextBlock]. We also add {{Icode|Microsoft.Xna.Framework}} reference into our project to find out the needle direction using {{Icode|MathHelper}} class.  
+
The {{Icode|MagneticHeading}}  gives the magnetic north pole value of the compass and is displayed in a [http://msdn.microsoft.com/en-us/library/system.windows.controls.textblock%28v=VS.95%29.aspx TextBlock]. We also add {{Icode|Microsoft.Xna.Framework}} reference into our project to find out the needle direction using {{Icode|MathHelper}} class.  
  
 
==Source Code==
 
==Source Code==
*The full source code of Qt example is available here: [[File:CompassQML_v1.1.zip]]
+
*The full source code of Qt example is available here: [[File:CompassQML v1.3.zip]]
*The full source code of WP7 example is available here: [[File:CompassWp7.zip]]
+
*The full source code of WP7 example is available here: [[File:CompassWp7.zip]]

Revision as of 08:45, 30 October 2012

This article demonstrates how to create a Compass in Qt and WP7.

WP Metro Icon WP8.png
SignpostIcon WP7 70px.png
Article Metadata
Code ExampleTested with
SDK: Windows Phone SDK 7.1, Qt SDK v1.2
Devices(s): N8 (Nokia Belle), Windows Phone
Compatibility
Platform(s): WP7.1, Symbian^3
Windows Phone 8
Windows Phone 7.5
Device(s): All with compass sensors in platform
Platform Security
Signing Required: Self-Signed
Capabilities: sensors
Article
Keywords: Compass, Sensors
Created: somnathbanik (16 Apr 2012)
Last edited: croozeus (30 Oct 2012)

Contents

Introduction

In this article we will create a Compass in QML using QML Compass Element which is a part of QtMobility 1.x and for WP7 we will use Compass Class. This is a magnetic compass used to determine the direction of the earth's magnetic north pole.

Compass using QML

Implementation

Let’s create an empty project for both Qt and WP7. First we will work on Qt project and then will move on to WP7 project.

Qt Project (MainPage.qml)

Let’s first create a circle using Rectangle Element as shown in the above figure. This circle will determine the compass outline. In QML Rectangle can be used to draw a circle with 1:1 dimensions and a radius.

Rectangle
{
id:circle
width: 250
height: 250
color: "transparent"
border.color: "green"
border.width: 3
radius: width*0.5
anchors.centerIn: parent
}

We add an Image to create the compass needle and rotate the Image with its change in degrees (angle).

 Image {
id: arrowImage
anchors.bottom: circle.verticalCenter
anchors.horizontalCenter: circle.horizontalCenter
height: circle.paintedHeight / 2
fillMode: Image.PreserveAspectFit
source: "upload.png"
rotation: -needleRotation
transformOrigin: Item.Bottom
}

QML Compass Element is used to get the change in magnetic north reading in the Compass.

 Compass {
id: compass
active: true
onReadingChanged: {
timerCompassCheck.running= false; //disable timer because Compass is working
mainPage.needleRotation = reading.azimuth;
}
}

We also set a Timer which expires after 7 seconds to check whether the compass is working properly (for example, it may not be supported on the device).

Timer {
id: timerCompassCheck
running: true
repeat: false
interval: 7000
onTriggered: {
compassTextError.visible=true;
}
}

As soon as the application launches the Timer starts running and expires after 7 seconds, the Timer doesn't repeat as the repeat property is set to false. When the onReadingChanged signal of the Compass Element is called it first stops the Timer and gets the compass reading and set it to needleRotation property which then used to rotate the compass needle angle. If within 7 seconds the signal onReadingChanged of the Compass Element is not called, then the Timer expires and displays a message that the device doesn't support compass. A Text element is being added to display the magnetic north value of the compass change on the device screen.

Text {
id:needleRotationText
text: needleRotation + " °N"
color: platformStyle.colorNormalLight
font.pixelSize: 35
anchors.top: parent.top
anchors.topMargin: 60
anchors.right: parent.right
anchors.rightMargin: 30
}

WP7 Project (MainPage.xaml)

To build a similar interface like Qt, let’s first create a circle using Ellipse Class which defines the outline of the compass.

<Ellipse StrokeThickness="2" x:Name="circle" Width="400" Height="400" 
Margin="0,90,0,0" Fill="Black">
<Ellipse.Stroke>
<SolidColorBrush Color="{StaticResource PhoneAccentColor}" />
</Ellipse.Stroke>
</Ellipse>

To create the compass needle we used Line Class.

<Line x:Name="line" X1="240" Y1="350" X2="240" Y2="270"  Stroke="{StaticResource PhoneForegroundBrush}" StrokeThickness="4"></Line>

Now we add the reference Microsoft.Devices.Sensors to initialize and detect the compass presence in the device.

Compass compass; 
if (Compass.IsSupported)
{
compass = new Compass();
compass.TimeBetweenUpdates = TimeSpan. FromSeconds(1);
compass.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<CompassReading>>(compass_CurrentValueChanged);
compass.Start();
}
else
{
MessageBox.Show("Device doesn't suport compass");
}

TimeBetweenUpdates property will update the compass data in every second. CurrentValueChanged event handler will give the compass value each time there is any change in the compass needle position. And then we call the Start() method to start the compass. The change in compass value is then passed to the compass_CurrentValueChanged() method. Which then pass to a separate thread using Dispatcher.BeginInvoke() method.

void compass_CurrentValueChanged(object sender, SensorReadingEventArgs<CompassReading> e)
{
Dispatcher.BeginInvoke(() => UpdateLine(e.SensorReading));
}
private void UpdateLine(CompassReading e)
{
degreeText.Text = e.MagneticHeading.ToString("0");
line.X2 = line.X1 - (200 * Math.Sin(MathHelper.ToRadians((float)e.MagneticHeading)));
line.Y2 = line.Y1 - (200 * Math.Cos(MathHelper.ToRadians((float)e.MagneticHeading)));
}

The MagneticHeading gives the magnetic north pole value of the compass and is displayed in a TextBlock. We also add Microsoft.Xna.Framework reference into our project to find out the needle direction using MathHelper class.

Source Code

199 page views in the last 30 days.