Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) QGraphicsObjectExample2

 

QGraphicsObject example 2: flashing is a QGraphicsObject example. It demonstrates how to use an internal QTimer to make the item flash.

 

 

QGraphicsObject example 3: flashing only is a simplification of this example.

Technical facts

 

Operating system(s) or programming environment(s)

IDE(s):

Project type:

C++ standard:

Compiler(s):

Libraries used:

 

 

 

 

 

Qt project file: ./CppQGraphicsObjectExample2/CppQGraphicsObjectExample2.pro

 

include(../../DesktopApplication.pri)

SOURCES += \
    qtmain.cpp \
    qtwidget.cpp \
    qtitem.cpp

HEADERS += \
    qtwidget.h \
    qtitem.h

RESOURCES += \
    CppQGraphicsObjectExample2.qrc

 

 

 

 

 

./CppQGraphicsObjectExample2/qtitem.h

 

#ifndef QTITEM_H
#define QTITEM_H

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <QGraphicsObject>
#include <boost/signals2.hpp>
#pragma GCC diagnostic pop

struct QPixmap;
struct QTimer;

///A QGraphicsObject that
/// - loads its pixmap from resources
/// - is clickable
/// - is movable
/// - changes the cursor
/// - can flash
class QtItem : public QGraphicsObject
{
  Q_OBJECT

  public:

  QtItem(QGraphicsItem *parent = 0);
  QtItem(const QtItem&) = delete;
  QtItem& operator=(const QtItem&) = delete;

  ///Lets this item flash
  void Flash();

  ///Signal emitted when clicked
  boost::signals2::signal<void (QtItem*)> m_clicked_signal;

  protected:
  void mousePressEvent(QGraphicsSceneMouseEvent *event);

  void hoverMoveEvent(QGraphicsSceneHoverEvent *event);

  QRectF boundingRect() const;

  void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);


  private:
  ///The number of flashes since flashing started
  int m_n_flashes;

  ///The pixmap
  boost::scoped_ptr<QPixmap> m_pixmap;

  ///Use QTimer because of its signals
  //Deleted by its parent (which is this item itself)
  QTimer * const m_timer;

  private slots:
  ///The event called when the item must flicker
  void FlashEvent();
};

#endif // QTITEM_H

 

 

 

 

 

./CppQGraphicsObjectExample2/qtitem.cpp

 


#include <cassert>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <QCursor>
#include <QPainter>
#include <QPixmap>
#include <QTimer>
#include "qtitem.h"
#pragma GCC diagnostic pop

QtItem::QtItem(QGraphicsItem *parent)
  : QGraphicsObject(parent),
    m_clicked_signal{},
    m_n_flashes{0},
    m_pixmap{new QPixmap(":/images/PicR.png")},
    m_timer{new QTimer(this)}
{
  assert(!m_pixmap->isNull()
    && "Assume pixmap is loaded successfully");

  this->setFlags(
      QGraphicsItem::ItemIsMovable
    | QGraphicsItem::ItemIsSelectable
  );


  //Without this line, hoverMoveEvent will not be called
  this->setAcceptHoverEvents(true);

  ///Set the interval between the flickers
  m_timer->setInterval(100); //100 ms

  QObject::connect(m_timer,SIGNAL(timeout()),
    this,SLOT(FlashEvent()));
}

QRectF QtItem::boundingRect() const
{
  const QRectF targetRect = m_pixmap->rect().translated(-m_pixmap->rect().center());
  assert(targetRect.center().x() >= -1.0);
  assert(targetRect.center().x() <=  1.0);
  assert(targetRect.center().y() >= -1.0);
  assert(targetRect.center().y() <=  1.0);
  return targetRect;
}

void QtItem::Flash()
{
  m_n_flashes = 0;
  m_timer->start();
}

void QtItem::FlashEvent()
{
  this->update();
  ++m_n_flashes;
  if (m_n_flashes == 10) { m_timer->stop(); }
}

void QtItem::hoverMoveEvent(QGraphicsSceneHoverEvent *)
{
  this->setCursor(QCursor(Qt::PointingHandCursor));
}

void QtItem::mousePressEvent(QGraphicsSceneMouseEvent *)
{
  //Emit the Boost signal
  m_clicked_signal(this);
}

void QtItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
  const QRectF targetRect = m_pixmap->rect().translated(-m_pixmap->rect().center());
  assert(targetRect.center().x() >= -1.0);
  assert(targetRect.center().x() <=  1.0);
  assert(targetRect.center().y() >= -1.0);
  assert(targetRect.center().y() <=  1.0);

  if (m_n_flashes % 2)
  {
    //Inverted pixmap
    QImage image = m_pixmap->toImage();
    image.invertPixels();
    QPixmap pixmap = QPixmap::fromImage(image);
    painter->drawPixmap(targetRect,pixmap,m_pixmap->rect());
  }
  else
  {
    //Regular pixmap
    painter->drawPixmap(targetRect,*m_pixmap,m_pixmap->rect());
  }

  //Draw a red line around the pixmap when it is selected
  if (this->isSelected())
  {
    painter->setPen(QPen(QColor(255,0,0),1));
    painter->drawRect(this->boundingRect().adjusted(1.0,1.0,-1.0,-1.0));
  }
}

 

 

 

 

 

./CppQGraphicsObjectExample2/qtmain.cpp

 

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <QApplication>
#include "qtwidget.h"
#pragma GCC diagnostic pop

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);
  QtWidget w;
  w.setGeometry(100,100,400,400);
  w.show();
  return a.exec();
}

 

 

 

 

 

./CppQGraphicsObjectExample2/qtwidget.h

 

#ifndef QTWIDGET_H
#define QTWIDGET_H

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <QGraphicsView>
#pragma GCC diagnostic pop

struct QtItem;

struct QtWidget : public QGraphicsView
{
  QtWidget();

  ///Respond to a click on a QtItem
  void OnItemClick(QtItem * const item);
};

#endif // QTWIDGET_H

 

 

 

 

 

./CppQGraphicsObjectExample2/qtwidget.cpp

 

#include <cassert>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <boost/bind.hpp>
#include <boost/lambda/bind.hpp>

#include <QGraphicsScene>
#include <QGraphicsPixmapItem>

#include "qtitem.h"
#include "qtwidget.h"
#pragma GCC diagnostic pop

QtWidget::QtWidget()
{
  QGraphicsScene * const scene = new QGraphicsScene(this);
  this->setScene(scene);

  const int n_items = 64;
  for (int i=0; i!=n_items; ++i)
  {
    QtItem * const item = new QtItem;
    item->m_clicked_signal.connect(
      boost::bind(
        &QtWidget::OnItemClick,this, boost::lambda::_1));
    //Scatter those items around a bit
    item->setPos(
      - 128 + (std::rand() % 256),
      - 128 + (std::rand() % 256));

    scene->addItem(item);
  }
}

void QtWidget::OnItemClick(QtItem * const item)
{
  item->Flash();
}

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml