January 19, 2011

kyleplattner kyleplattner
Lab Rat
242 posts

Distinguishing direction of swipe and changing states accordingly in QML

 

This should be fairly simple but I am not sure how to complete it. Lets say I have several states that I want to switch between by swipe events so that when the user swipes to the left it goes back one state and when the user swipes to the right it goes forward one state. Any help would be appreciated. Thanks,

Kyle

11 replies

January 19, 2011

Andre Andre
Area 51 Engineer
6031 posts

I assume you are using the GestureArea QML element, right?
The onSwipe signal has an angle argument. You can use that to distinguish a direction. I don’t know what the scale (degrees? rads?) or what the 0 point is (top? right?), but you should be able to figure that out yourself easily. Say that the scale are degrees and the top is 0, then you can interpret anything between 315 and 360 and between 0 and 45 as a swipe to the top, between 45 and 135 to the right, between 135 and 225 to the bottom, and between 225 and 315 to the left.

The state system in QML is quite basic (there were discussions on integrating the much more powerful Qt statemachines into QML here or on the qml mailinglist before), but in principle, you can just change the qml state that controls in what state your application is on such a swipe.

 Signature 

Looking for Qt developers to join our team @ i-Optics: https://qt-project.org/forums/viewthread/25393/

January 19, 2011

kyleplattner kyleplattner
Lab Rat
242 posts

I would like to do with with just a mousearea so I don’t have to use a labs plugin. This will be necessary to move to my target device, openembedded linux. Any solutions with mousearea?

January 19, 2011

Andre Andre
Area 51 Engineer
6031 posts

Well, in that case, you would basically have to make your own gesture recognition. For a very basic recognition, store the x and of the mouse when you receive the onPressed signal, and compare with the x and y when you get onReleased. If the x on release is (much) bigger than on pressed, and the y is about the same, you have a swipe to the right. You probably want to add the time it took into the picture, as well as detours along the way (a half circle is not the same as a swipe, even though they can start and end in the same place).

Are you sure you can’t use the one from labs somehow?

 Signature 

Looking for Qt developers to join our team @ i-Optics: https://qt-project.org/forums/viewthread/25393/

January 19, 2011

kyleplattner kyleplattner
Lab Rat
242 posts

I believe I understand the concept, I am just not sure how to accomplish it in qml. Deploying plugins to openembedded has been a large nightmare in the past.

January 19, 2011

matrixx matrixx
Lab Rat
50 posts

I have implemented the swipe gesture in my QML jewel-game. I’ll paste the code (JavaScript) which handles the swipe gesture check for MouseArea component here. The code is my game specific, but I’m sure you’ll get the idea :)

  1. function handleSwipe(srcX, srcY, destX, destY) {
  2.     var col = Math.floor(srcX / gameCanvas.blockSize);
  3.     var row = Math.floor(srcY / gameCanvas.blockSize);
  4.     if (col >= maxColumn || col < 0 || row >= maxRow || row < 0)
  5.         return false;
  6.  
  7.     var deltax = destX - srcX;
  8.     var deltay = destY - srcY;
  9.     var success = false;
  10.     if (Math.abs(deltax) > 50 || Math.abs(deltay) > 50) {
  11.         if (deltax > 30 && Math.abs(deltay) < 30) {
  12.             // swipe right
  13.             success = trySwap(col, row, col + 1, row);
  14.         } else if (deltax < -30 && Math.abs(deltay) < 30) {
  15.             // swipe left
  16.             success = trySwap(col, row, col - 1, row);
  17.         } else if (Math.abs(deltax) < 30 && deltay > 30) {
  18.             // swipe down
  19.             success = trySwap(col, row, col, row + 1);
  20.         } else if (Math.abs(deltax) < 30 && deltay < 30) {
  21.             // swipe up
  22.             success = trySwap(col, row, col, row - 1);
  23.         }
  24.         if (success) {
  25.             shuffleDown();
  26.             fillBoard();
  27.             return true;
  28.         }
  29.     }
  30.     return false;
  31. }

 Signature 

Nokia Certified Qt Specialist

January 19, 2011

kyleplattner kyleplattner
Lab Rat
242 posts

Could you help me understand how your JavaScript integrated into your QML mousearea and where I would need to modify our JavaScript?

How could I have the JavaScript tell my mousearea when a gesture is signaled. In other words, I would love to have my mouse area designed like:

Mousearea{

onGestureLeft:
}

January 19, 2011

Andre Andre
Area 51 Engineer
6031 posts

You can achieve that by creating your own QML component with the appropriate signals.
Adapt the code example above to emit such a signal on the different swipes that it recognizes (see the inline comments on when that is).

On the start of your mouse interaction, you store the begin coordinates xB and yB. If you want to recognize the swipe only when the interaction is over, you then use the onReleased signal of the mouseArea. If you want to do continuous recognition, use the onPositionChanged signal. When you get the required signal, run the code above using the xB and yB and the new coordinates that are passed with the signal.

 Signature 

Looking for Qt developers to join our team @ i-Optics: https://qt-project.org/forums/viewthread/25393/

January 19, 2011

kyleplattner kyleplattner
Lab Rat
242 posts

Forgive my inexperience but could you give me an example of what that would look like?

January 19, 2011

Andre Andre
Area 51 Engineer
6031 posts

From the top of my head, I did not try it out:

  1. //in a file called MyGestureArea.qml (casing important!)
  2.  
  3. MouseArea {
  4.     signal swipeRight;
  5.     signal swipeLeft;
  6.     signal swipeUp;
  7.     signal swipeDown;
  8.  
  9.     property int startX;
  10.     property int startY;
  11.  
  12.     onPressed: {
  13.         startX = mouse.x;
  14.         startY = mouse.y;
  15.     }
  16.  
  17.     onReleased: {
  18.     var deltax = mouse.x - startX;
  19.     var deltay = mouse.y - startY;
  20.  
  21.     if (Math.abs(deltax) > 50 || Math.abs(deltay) > 50) {
  22.         if (deltax > 30 && Math.abs(deltay) < 30) {
  23.             // swipe right
  24.             swipeRight();
  25.         } else if (deltax < -30 && Math.abs(deltay) < 30) {
  26.             // swipe left
  27.             swipeLeft();
  28.         } else if (Math.abs(deltax) < 30 && deltay > 30) {
  29.             // swipe down
  30.             swipeDown();
  31.         } else if (Math.abs(deltax) < 30 && deltay < 30) {
  32.             // swipe up
  33.             swipeUp();
  34.         }
  35.     }
  36. }

Then, you should be able to use a MyGestureArea instead of a MouseArea, and be able to use onSwipeRight and onSwipeDown event handlers. Again: I did not test the above. See it as pseudocode please :-)

 Signature 

Looking for Qt developers to join our team @ i-Optics: https://qt-project.org/forums/viewthread/25393/

January 19, 2011

kyleplattner kyleplattner
Lab Rat
242 posts

That worked great but it does not play well with my other mouseareas on the page. I laid the gesture sensing mousearea over the whole page which contains mousareas for buttons.

November 18, 2011

music24by7 music24by7
Lab Rat
4 posts

Thank you guys, I was looking out for an example as this: I implemented it as below in my flip area

  1. MouseArea{
  2.         id:myFlipMouseArea
  3.         anchors.fill: myFlip
  4.         property int startX;
  5.         property int startY;
  6.         onPressed: {
  7.             startX = mouse.x;
  8.             startY = mouse.y;
  9.         }
  10.  
  11.         onReleased: {
  12.             var deltax = mouse.x - startX;
  13.             var deltay = mouse.y - startY;
  14.  
  15.             if (Math.abs(deltax) > 40 || Math.abs(deltay) > 40) {
  16.                 if (deltax > 30 && Math.abs(deltay) < 30) {
  17.                     // swipe right
  18.                 } else if (deltax < -30 && Math.abs(deltay) < 30) {
  19.                     // swipe left
  20.                     myFlip.flipped = !myFlip.flipped
  21.                     console.log("swipeLeft");
  22.                 } else if (Math.abs(deltax) < 30 && deltay > 30) {
  23.                     // swipe down
  24.                 } else if (Math.abs(deltax) < 30 && deltay < 30) {
  25.                     // swipe up
  26.                     console.log("swipeUp");
  27.                     currentWord += 1;
  28.                     flipWord.modifyContents();
  29.                 }
  30.             }
  31.         }
  32.     }

 
  ‹‹ FontLoader on Symbian platform      How to Install QSparql ››

You must log in to post a reply. Not a member yet? Register here!