(C++) QGraphicsSimpleTextItemExample5

February 24, 2017 · View on GitHub

 

 

 

 

 

(C++) QGraphicsSimpleTextItemExample5

 

QtQt
CreatorLubuntu

 

QGraphicsSimpleTextItem example 5: keyboard-friendly view is a QGraphicsSimpleTextItem example that displays multiple QGraphicsSimpleTextItems with their coordinats as text. These items are movable and selectable. By pressing space, focus will be set to a random item. By pressing an arrow keys, focus will be given to the nearest item in that direction. By pressing an arrow key while holding shift, the item is moved.

 

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: ./CppQGraphicsSimpleTextItemExample5/CppQGraphicsSimpleTextItemExample5.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

 

 

 

 

 

./CppQGraphicsSimpleTextItemExample5/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(); }

 

 

 

 

 

./CppQGraphicsSimpleTextItemExample5/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

 

 

 

 

 

./CppQGraphicsSimpleTextItemExample5/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); }

 

 

 

 

 

./CppQGraphicsSimpleTextItemExample5/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;   ///Calculate the Euclidian distance between two points   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

 

 

 

 

 

./CppQGraphicsSimpleTextItemExample5/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 <QGraphicsSimpleTextItem> #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);     //item->setPos(QPointF(x,y)-item->boundingRect().center());     scene()->addItem(item);   }   {     QGraphicsSimpleTextItem * const item = new QGraphicsSimpleTextItem(       "Arrow: move focus\n"       "Shift + arrow: move item\n"       "Space: go to random item"       );     item->setPos(this->mapToScene(40,40));     item->setFlags(         QGraphicsItem::ItemIsFocusable       | QGraphicsItem::ItemIsMovable       | QGraphicsItem::ItemIsSelectable);     scene()->addItem(item);   } } QGraphicsItem * QtWidget::GetClosest(   const QGraphicsItem * const focus_item,   const std::vector<QGraphicsItem *>& items) const {   assert(!items.empty());   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) {   if (event->modifiers() & Qt::ShiftModifier)   {     switch (event->key())     {       case Qt::Key_Up:       {         QGraphicsItem * const focus_item = scene()->focusItem();         if (!focus_item) { return; }         focus_item->setPos(focus_item->pos() + QPointF(0.0,-10.0));         return;       }       case Qt::Key_Right:       {         QGraphicsItem * const focus_item = scene()->focusItem();         if (!focus_item) { return; }         focus_item->setPos(focus_item->pos() + QPointF(10.0,0.0));         return;       }       case Qt::Key_Down:       {         QGraphicsItem * const focus_item = scene()->focusItem();         if (!focus_item) { return; }         focus_item->setPos(focus_item->pos() + QPointF(0.0,10.0));         return;       }       case Qt::Key_Left:       {         QGraphicsItem * const focus_item = scene()->focusItem();         if (!focus_item) { return; }         focus_item->setPos(focus_item->pos() + QPointF(-10.0,0.0));         return;       }     }   }   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_Tab:     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:     case Qt::Key_Backtab:     {       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_Space:     {       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(); }