Qt Mobility Reference Documentation

Haptic Square Example

Files:

Overview

This example shows how to use simple haptic effects in an application via the Qt Mobility Feedback API.

It provides an example of how to use the Qt Mobility libraries to:

  • play "system theme" haptic effects corresponding to certain predefined events
  • play a custom effect, single or repeating

Use Case

Compelling applications attempt to immerse the user in the application experience. There are many elements to an immersive experience, including a consistent and beautiful graphical user interface design, unobtrusive yet informative sound design, and intuitive program flow. Another important aspect of immersive applications in tactile feedback and haptic effects.

The Qt Mobility Feedback API allows application developers to include tactile feedback into their application via a simple to use and extensible API. Some common uses for tactile feedback are:

  • maintain consistency with system theme for tactile feedback about interface events (button clicks, scrolling, etc)
  • notify the user of an application-specific event (invalid operation, status change, etc)
  • multisensory user interface (status can be "read" by touching the screen, tactile interfaces, etc)
  • immersive gaming experiences (explosions, impacts, collisions, etc)

This example application provides some short snippets which illustrate how the first two of those use cases may be fulfilled.

The Application

The application is designed to work on desktop and mobile platforms with minimal differences in code between the platforms. The interface consists of four buttons arranged into a square, each of which causes a different tactile effect to be played by the default tactile effect provider plugin on the platform.

  • "Rumble!" plays a non-repeating effect with symmetric attack and decay
  • "Ocean" is a toggle button which plays a repeating ocean wave-like effect
  • "Click" plays the system theme effect for a basic button click
  • "Oops!" plays the system theme effect for a negative or invalid response

The example implements two classes:

  • HapticButton: Implementation of a button. It inherits QWidget and sends signals for button clicks. It can also be a toggle button.
  • Dialog: A QDialog subclass that displays the four HapticButtons mentioned above, connects them to its slots, and implements the functionality to play the haptic effects.

The Dialog Class

We will now go through the code for the Dialog class. Here is its definition:

 class HapticSquare : public QWidget
 {
     Q_OBJECT

 public:
     HapticSquare();
     ~HapticSquare();

 private Q_SLOTS:
     void playRumble();
     void playOcean(bool toggleState);
     void playButtonClick();
     void playNegativeEffect();

 private:
     HapticButton *m_btnRumble;
     HapticButton *m_btnOcean;
     HapticButton *m_btnButtonClick;
     HapticButton *m_btnNegativeEffect;

     QFeedbackHapticsEffect m_rumble;
     QFeedbackHapticsEffect m_ocean;
 };

The buttons are connected to the slots, which play the effects. We will now go through the implementation of Dialog.

The constructor starts by setting up the non-repeating haptic effect, which is played by clicking the Rumble! Button.

 HapticSquare::HapticSquare()
 {
     m_rumble.setAttackIntensity(0.0);
     m_rumble.setAttackTime(250);
     m_rumble.setIntensity(1.0);
     m_rumble.setDuration(100);
     m_rumble.setFadeTime(250);
     m_rumble.setFadeIntensity(0.0);

Custom haptics effects are created by setting up a QFeedbackHapticsEffect.

A haptics effect provides a fade-in of the effect's intensity(). With vibration, you can think of the intensity as how hard the device will vibrate. The effect will start at attackIntensity() and interpolate to intensity() in attackTime() milliseconds. When the effect ends, we have a similar fade-out, where the haptics effect's intensity will interpolate from intensity() to fadeTime() in fadeTime() milliseconds. The effect's intensity will stay at the peak value for duration() milliseconds.

We next set up the effect for the Ocean Button.

     m_ocean.setAttackIntensity(0.0);
     m_ocean.setAttackTime(450);
     m_ocean.setIntensity(0.8);
     m_ocean.setDuration(150);
     m_ocean.setFadeTime(900);
     m_ocean.setFadeIntensity(0.05);
     m_ocean.setPeriod(1500);

The m_ocean is a periodic effect, i.e., it repeats after period() milliseconds. To stop a periodic effect, you must call stop().

We then set up the GUI and connects the buttons to slots that will play the effects.

     m_btnRumble = new HapticButton(tr("Rumble!"));
     m_btnOcean = new HapticButton(tr("Ocean"));
     m_btnOcean->setCheckable(true);
     m_btnButtonClick = new HapticButton(tr("Click"));
     m_btnNegativeEffect = new HapticButton(tr("Oops!"));
     QGridLayout *topLayout = new QGridLayout(this);
     topLayout->addWidget(m_btnRumble, 0, 0);
     topLayout->addWidget(m_btnOcean, 0, 1);
     topLayout->addWidget(m_btnButtonClick, 1, 0);
     topLayout->addWidget(m_btnNegativeEffect, 1, 1);

     connect(m_btnRumble, SIGNAL(clicked()), this, SLOT(playRumble()));
     connect(m_btnOcean, SIGNAL(toggled(bool)), this, SLOT(playOcean(bool)));
     connect(m_btnButtonClick, SIGNAL(clicked()), this, SLOT(playButtonClick()));
     connect(m_btnNegativeEffect, SIGNAL(clicked()), this, SLOT(playNegativeEffect()));
 }

Let's look at the slots to see how the effects are played.

 void HapticSquare::playRumble()
 {
     m_rumble.start();
 }

 void HapticSquare::playOcean(bool toggleState)
 {
     if (toggleState)
         m_ocean.start();
     else
         m_ocean.stop();
 }

With the m_rumble, we only have to call start(). It will stop when the effect has finished, and can be played again by calling start() again.

The periodic m_ocean effect is started the same way as the m_rumble effect, but must be stopped with the stop() function. It will start playing from the beginning again when start() is called. We could also have paused the effect with pause().

 void HapticSquare::playButtonClick()
 {
     QFeedbackEffect::playThemeEffect(QFeedbackEffect::ThemeBasicButton);
 }

 void HapticSquare::playNegativeEffect()
 {
     QFeedbackEffect::playThemeEffect(QFeedbackEffect::ThemeNegativeTacticon);
 }

System theme effects are played with the static QFeedbackEffect::playThemeEffect() function. Theme effects cannot be stopped or paused. There is no guarantee that the backend can play the effect; playThemeEffect() will return false if the effect could not be played.

Known Issues

The example is not intended to exercise the entire API. Instead, it is a simple example which illustrates some simple uses of the API. Also, the example will not work correctly on platforms which do not have a QFeedbackHapticInterface (haptic effect provider) plugin loaded. On such platforms, clicking the buttons will have no effect.

In particular, the Maemo5 platform currently has no haptic effect provider plugin; it is a work in progress.

X

Thank you for giving your feedback.

Make sure it is related to this specific page. For more general bugs and requests, please use the Qt Bug Tracker.