(C++) QGraphicsSimpleTextItemExample4

March 5, 2018 · View on GitHub

QGraphicsSimpleTextItem example 4: use arrow keys to change focus is a QGraphicsSimpleTextItem example that displays multiple QGraphicsSimpleTextItems with their coordinats as text. These items are movable and selectable. By pressing tab, focus will be set to a random item. By pressing the arrow, focus will be given to the nearest item in that direction.

View a screenshot of 'QGraphicsSimpleTextItemExample4' (png)

Technical facts

 

Application type(s)

Operating system(s) or programming environment(s)

IDE(s):

Project type:

C++ standard:

Compiler(s):

Libraries used:

  • Qt Qt: version 5.4.1 (32 bit)
  • STL STL: GNU ISO C++ Library, version 4.9.2

 

 

 

 

 

Qt project file: ./CppQGraphicsSimpleTextItemExample4/CppQGraphicsSimpleTextItemExample4.pro

 


exists(../../DesktopApplication.pri) {   include(../../DesktopApplication.pri) } !exists(../../DesktopApplication.pri) {   QT       += core gui   greaterThan(QT_MAJOR_VERSION, 4): QT += widgets   win32 {     greaterThan(QT_MAJOR_VERSION, 4): QT += svg   }   TEMPLATE = app   CONFIG(debug, debug|release) {     message(Debug mode)   }   CONFIG(release, debug|release) {     message(Release mode)     DEFINES += NDEBUG NTRACE_BILDERBIKKEL   }   QMAKE_CXXFLAGS += -std=c++1y -Wall -Wextra -Weffc++   unix {     QMAKE_CXXFLAGS += -Werror   } } exists(../../Libraries/Boost.pri) {   include(../../Libraries/Boost.pri) } !exists(../../Libraries/Boost.pri) {   INCLUDEPATH += \     ../../Libraries/boost_1_55_0 } SOURCES += \     qtmain.cpp \     qtwidget.cpp \     qttextitem.cpp HEADERS += \     qtwidget.h \     qttextitem.h

 

 

 

 

 

./CppQGraphicsSimpleTextItemExample4/qtmain.cpp

 


#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include <QApplication> #include <QDesktopWidget> #include "qtwidget.h" #pragma GCC diagnostic pop int main(int argc, char *argv[]) {   QApplication a(argc, argv);   QtWidget w;   {     //Resize the dialog and put it in the screen center     w.setGeometry(0,0,600,400);     const QRect screen = QApplication::desktop()->screenGeometry();     w.move( screen.center() - w.rect().center() );   }   w.show();   return a.exec(); }

 

 

 

 

 

./CppQGraphicsSimpleTextItemExample4/qttextitem.h

 


#ifndef QTTEXTITEM_H #define QTTEXTITEM_H #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include <QGraphicsSimpleTextItem> #pragma GCC diagnostic pop struct QtTextItem : public QGraphicsSimpleTextItem {   QtTextItem(QGraphicsItem *parent = 0);   void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); }; #endif // QTTEXTITEM_H

 

 

 

 

 

./CppQGraphicsSimpleTextItemExample4/qttextitem.cpp

 


#include "qttextitem.h" #include <cassert> #include <sstream> #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include <QGraphicsScene> #pragma GCC diagnostic pop QtTextItem::QtTextItem(QGraphicsItem *parent) : QGraphicsSimpleTextItem(parent) {   this->setFlags(       QGraphicsItem::ItemIsFocusable     | QGraphicsItem::ItemIsMovable     | QGraphicsItem::ItemIsSelectable); } void QtTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {   std::stringstream s;   s << "(" << static_cast<int>(this->pos().x()) << "," << static_cast<int>(this->pos().y()) << ")";   this->setText(s.str().c_str());   QGraphicsSimpleTextItem::paint(painter,option,widget); }

 

 

 

 

 

./CppQGraphicsSimpleTextItemExample4/qtwidget.h

 


#ifndef QTWIDGET_H #define QTWIDGET_H #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include <QGraphicsView> #pragma GCC diagnostic pop ///The widget holding the items struct QtWidget : public QGraphicsView {   QtWidget(QWidget *parent = 0);   ///Respond to a key press   void keyPressEvent(QKeyEvent *event);   private:   ///Obtain the closest item in the collection   QGraphicsItem * GetClosest(     const QGraphicsItem * const focus_item,     const std::vector<QGraphicsItem *>& items) const;   static double GetDistance(const QPointF& a, const QPointF& b);   ///Obtain the items above the focus_item   const std::vector<QGraphicsItem *> GetItemsAbove(const QGraphicsItem * const focus_item) const;   ///Obtain the items below the focus_item   const std::vector<QGraphicsItem *> GetItemsBelow(const QGraphicsItem * const focus_item) const;   ///Obtain the items left of the focus_item   const std::vector<QGraphicsItem *> GetItemsLeft(const QGraphicsItem * const focus_item) const;   ///Obtain the items right of the focus_item   const std::vector<QGraphicsItem *> GetItemsRight(const QGraphicsItem * const focus_item) const;   ///Give focus to a random item   void SetRandomFocus(); }; #endif // QTWIDGET_H

 

 

 

 

 

./CppQGraphicsSimpleTextItemExample4/qtwidget.cpp

 


#include "qtwidget.h" #include <cassert> #include <cmath> #include <iostream> #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include <boost/math/constants/constants.hpp> #include <QGraphicsScene> #include <QKeyEvent> #include "qttextitem.h" #pragma GCC diagnostic pop QtWidget::QtWidget(QWidget *parent)   : QGraphicsView(new QGraphicsScene,parent) {   const int n_items = 16;   for (int i=0; i!=n_items; ++i)   {     const double angle       = boost::math::constants::two_pi<double>()       * (static_cast<double>(i+0) / static_cast<double>(n_items));     const double ray = 150.0;     const double x =  std::sin(angle) * ray;     const double y = -std::cos(angle) * ray;     QtTextItem * const item = new QtTextItem;     item->setPos(x,y);     scene()->addItem(item);   } } QGraphicsItem * QtWidget::GetClosest(   const QGraphicsItem * const focus_item,   const std::vector<QGraphicsItem *>& items) const {   assert(!items.empty());   //Remove focus item for items_all (if needed)   //std::vector<QGraphicsItem *> items(items_all);   //items.erase(std::remove(items.begin(),items.end(),focus_item),items.end());   assert(std::count(items.begin(),items.end(),focus_item) == 0);   QGraphicsItem * best = nullptr;   double best_distance = std::numeric_limits<double>::max();   for (QGraphicsItem * const item:items)   {     assert(item != focus_item);     const double distance = GetDistance(focus_item->pos(),item->pos());     if (distance < best_distance)     {       best_distance = distance;       best = item;     }   }   assert(best);   return best; } double QtWidget::GetDistance(const QPointF& a, const QPointF& b) {   const double dx = a.x() - b.x();   const double dy = a.y() - b.y();   return std::sqrt((dx * dx) + (dy * dy)); } const std::vector<QGraphicsItem *> QtWidget::GetItemsAbove(const QGraphicsItem * const focus_item) const {   std::vector<QGraphicsItem *> v;   const QList<QGraphicsItem *> items = this->items();   for(QGraphicsItem * const item: items)   {     const double dy = item->pos().y() - focus_item->pos().y();     if (dy < 0.0)  //Use '<' (instead of '<=') to leave out focus_item     {       const double dx = item->pos().x() - focus_item->pos().x();       if (std::abs(dx) < std::abs(dy))       {         assert(item != focus_item);         v.push_back(item);       }     }   }   return v; } const std::vector<QGraphicsItem *> QtWidget::GetItemsBelow(const QGraphicsItem * const focus_item) const {   std::vector<QGraphicsItem *> v;   const QList<QGraphicsItem *> items = this->items();   for(QGraphicsItem * const item: items)   {     const double dy = item->pos().y() - focus_item->pos().y();     if (dy > 0.0)  //Use '>' (instead of '>=') to leave out focus_item     {       const double dx = item->pos().x() - focus_item->pos().x();       if (std::abs(dx) < std::abs(dy))       {         assert(item != focus_item);         v.push_back(item);       }     }   }   return v; } const std::vector<QGraphicsItem *> QtWidget::GetItemsLeft(const QGraphicsItem * const focus_item) const {   std::vector<QGraphicsItem *> v;   const QList<QGraphicsItem *> items = this->items();   for(QGraphicsItem * const item: items)   {     const double dx = item->pos().x() - focus_item->pos().x();     if (dx < 0.0)  //Use '<' (instead of '<=') to leave out focus_item     {       const double dy = item->pos().y() - focus_item->pos().y();       if (std::abs(dy) < std::abs(dx))       {         assert(item != focus_item);         v.push_back(item);       }     }   }   return v; } const std::vector<QGraphicsItem *> QtWidget::GetItemsRight(const QGraphicsItem * const focus_item) const {   std::vector<QGraphicsItem *> v;   const QList<QGraphicsItem *> items = this->items();   for(QGraphicsItem * const item: items)   {     const double dx = item->pos().x() - focus_item->pos().x();     if (dx > 0.0) //Use '>' (instead of '>=') to leave out focus_item     {       const double dy = item->pos().y() - focus_item->pos().y();       if (std::abs(dy) < std::abs(dx))       {         assert(item != focus_item);         v.push_back(item);       }     }   }   return v; } void QtWidget::keyPressEvent(QKeyEvent *event) {   switch (event->key())   {     case Qt::Key_Up:     {       QGraphicsItem * const focus_item = scene()->focusItem();       if (!focus_item) { return; }       const std::vector<QGraphicsItem *> items = GetItemsAbove(focus_item);       if (items.empty()) { return; }       QGraphicsItem * const new_focus_item = GetClosest(focus_item,items);       focus_item->setEnabled(false);       focus_item->clearFocus();       focus_item->setEnabled(true);       new_focus_item->setFocus();     }     break;     case Qt::Key_Right:     {       QGraphicsItem * const focus_item = scene()->focusItem();       if (!focus_item) { return; }       const std::vector<QGraphicsItem *> items = GetItemsRight(focus_item);       if (items.empty()) { return; }       QGraphicsItem * const new_focus_item = GetClosest(focus_item,items);       focus_item->setEnabled(false);       focus_item->clearFocus();       focus_item->setEnabled(true);       new_focus_item->setFocus();     }     break;     case Qt::Key_Down:     {       QGraphicsItem * const focus_item = scene()->focusItem();       if (!focus_item) { return; }       const std::vector<QGraphicsItem *> items = GetItemsBelow(focus_item);       if (items.empty()) { return; }       QGraphicsItem * const new_focus_item = GetClosest(focus_item,items);       focus_item->setEnabled(false);       focus_item->clearFocus();       focus_item->setEnabled(true);       new_focus_item->setFocus();     }     break;     case Qt::Key_Left:     {       QGraphicsItem * const focus_item = scene()->focusItem();       if (!focus_item) { return; }       const std::vector<QGraphicsItem *> items = GetItemsLeft(focus_item);       if (items.empty()) { return; }       QGraphicsItem * const new_focus_item = GetClosest(focus_item,items);       focus_item->setEnabled(false);       focus_item->clearFocus();       focus_item->setEnabled(true);       new_focus_item->setFocus();     }     break;     case Qt::Key_Tab:     {       SetRandomFocus();     }     break;   }   //Let QGraphicsView do the rest...   QGraphicsView::keyPressEvent(event); } void QtWidget::SetRandomFocus() {   //Let existing item lose focus   if (QGraphicsItem * const item = scene()->focusItem())   {     //Really lose focus     item->setEnabled(false);     item->clearFocus();     item->setEnabled(true);   }   //Let a random item receive focus   const QList<QGraphicsItem *> items = this->items();   items.at( std::rand() % items.size() )->setFocus(); }