(C++) QtExample35

February 24, 2017 · View on GitHub

 

 

 

 

 

(C++) QtExample35

 

QtQt
CreatorLubuntu

 

Qt example 35: arrows with an angle is a Qt example elaborates on Qt example 34: moveable, selectable and editable arrows, but has arrows with an angle in them instead.

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: ./CppQtExample35/CppQtExample35.pro

 


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

 

 

 

 

 

./CppQtExample35/qtarrowitem.h

 


#ifndef QTARROWITEM_H #define QTARROWITEM_H #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include <QGraphicsLineItem> #pragma GCC diagnostic pop struct QtArrowItem : public QGraphicsItem {   QtArrowItem(     const double tail_x,     const double tail_y,     const bool tail,     const double mid_x,     const double mid_y,     const bool head,     const double head_x,     const double head_y,     QGraphicsItem *parent = 0);   ///Respond to key presses   void keyPressEvent(QKeyEvent *event);   protected:   ///The rectangle that containg the item, used for rough calculations like   ///collision detection   QRectF boundingRect() const;   ///Respond to mouse press   void mousePressEvent(QGraphicsSceneMouseEvent *event);   ///Paint a QtTextPositionItem   void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *);   ///More precise shape compared to boundingRect   ///In this example, it is redefined to ease selecting those thin lines   QPainterPath shape() const;   private:   ///The extra width given to the line for easier clicking   static const double m_click_easy_width;   ///Show arrow at head   bool m_head;   double m_head_x;   double m_head_y;   double m_mid_x;   double m_mid_y;   ///Show arrow at tail   bool m_tail;   double m_tail_x;   double m_tail_y;   ///Obtain the angle in radians between two deltas   ///12 o'clock is 0.0 * pi   /// 3 o'clock is 0.5 * pi   /// 6 o'clock is 1.0 * pi   /// 9 o'clock is 1.5 * pi   //From www.richelbilderbeek.nl/CppGetAngle.htm   static double GetAngle(const double dx, const double dy); }; #endif // QTARROWITEM_H

 

 

 

 

 

./CppQtExample35/qtarrowitem.cpp

 


#include <cassert> #include <cmath> #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include <boost/math/constants/constants.hpp> #include <QGraphicsSceneMouseEvent> #include <QKeyEvent> #include <QPainter> #include "qtarrowitem.h" #pragma GCC diagnostic pop const double QtArrowItem::m_click_easy_width = 10.0; QtArrowItem::QtArrowItem(   const double tail_x,   const double tail_y,   const bool tail,   const double mid_x,   const double mid_y,   const bool head,   const double head_x,   const double head_y,   QGraphicsItem *parent)   : QGraphicsItem(parent),     m_head(head),     m_head_x(head_x),     m_head_y(head_y),     m_mid_x(mid_x),     m_mid_y(mid_y),     m_tail(tail),     m_tail_x(tail_x),     m_tail_y(tail_y) {   this->setFlag(QGraphicsItem::ItemIsMovable);   this->setFlag(QGraphicsItem::ItemIsSelectable); } double QtArrowItem::GetAngle(const double dx, const double dy) {   return boost::math::constants::pi<double>() - (std::atan(dx/dy)); } QRectF QtArrowItem::boundingRect() const {   return shape().boundingRect(); } void QtArrowItem::keyPressEvent(QKeyEvent *event) {   switch (event->key())   {     case Qt::Key_F1:     case Qt::Key_1:     case Qt::Key_T:     case Qt::Key_Minus:       m_tail = !m_tail;       this->update();       break;     case Qt::Key_F2:     case Qt::Key_2:     case Qt::Key_H:     case Qt::Key_Plus:       m_head = !m_head;       this->update();       break;     default:       break;   } } void QtArrowItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {   if (event->modifiers() & Qt::ShiftModifier)   {     if ((event->pos() - QPointF(m_tail_x,m_tail_y)).manhattanLength() < 10.0)     {       m_tail = !m_tail;       this->update();     }     else if ((event->pos() - QPointF(m_head_x,m_head_y)).manhattanLength() < 10.0)     {       m_head = !m_head;       this->update();     }   } } void QtArrowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {   painter->setRenderHint(QPainter::Antialiasing);   if (this->isSelected())   {     const QColor color(255,0,0);     QPen pen;     pen.setColor(color);     pen.setWidth(3);     painter->setPen(pen);     QBrush brush;     brush.setColor(color);     brush.setStyle(Qt::SolidPattern);     painter->setBrush(brush);   }   else   {     const QColor color(0,0,0);     QPen pen;     pen.setColor(color);     pen.setWidth(1);     painter->setPen(pen);     QBrush brush;     brush.setColor(color);     brush.setStyle(Qt::SolidPattern);     painter->setBrush(brush);   }   painter->drawLine(     m_tail_x,m_tail_y,     m_mid_x ,m_mid_y);   painter->drawLine(     m_mid_x,m_mid_y,     m_head_x,m_head_y);   const double sz = 10.0; //pixels   if (m_tail)   {     const double dx = m_mid_x - m_tail_x;     const double dy = m_mid_y - m_tail_y;     double angle = GetAngle(dx,dy);     if (dy >= 0.0) angle = (1.0 * boost::math::constants::pi<double>()) + angle;     const QPointF p0(m_tail_x,m_tail_y);     const QPointF p1       = p0 + QPointF(          std::sin(angle + boost::math::constants::pi<double>() + (boost::math::constants::pi<double>() * 0.1)) * sz,         -std::cos(angle + boost::math::constants::pi<double>() + (boost::math::constants::pi<double>() * 0.1)) * sz);     const QPointF p2       = p0 + QPointF(          std::sin(angle + boost::math::constants::pi<double>() - (boost::math::constants::pi<double>() * 0.1)) * sz,         -std::cos(angle + boost::math::constants::pi<double>() - (boost::math::constants::pi<double>() * 0.1)) * sz);     painter->drawPolygon(QPolygonF() << p0 << p1 << p2);   }   if (m_head)   {     const double dx = m_head_x - m_mid_x;     const double dy = m_head_y - m_mid_y;     double angle = GetAngle(dx,dy);     if (dy >= 0.0) angle = (1.0 * boost::math::constants::pi<double>()) + angle;     const QPointF p0(m_head_x,m_head_y);     const QPointF p1       = p0 + QPointF(          std::sin(angle +  0.0 + (boost::math::constants::pi<double>() * 0.1)) * sz,         -std::cos(angle +  0.0 + (boost::math::constants::pi<double>() * 0.1)) * sz);     const QPointF p2       = p0 + QPointF(          std::sin(angle +  0.0 - (boost::math::constants::pi<double>() * 0.1)) * sz,         -std::cos(angle +  0.0 - (boost::math::constants::pi<double>() * 0.1)) * sz);     painter->drawPolygon(QPolygonF() << p0 << p1 << p2);   } } QPainterPath QtArrowItem::shape() const {   //Thanks to norobro for posting this code at   //http://www.qtcentre.org/threads/49201-Increase-margin-for-detecting-tooltip-events-of-QGraphicsLineItem   QPainterPath path;   QPainterPathStroker stroker;   path.moveTo(m_tail_x,m_tail_y);   path.lineTo(m_mid_x,m_mid_y);   path.lineTo(m_head_x,m_head_y);   stroker.setWidth(m_click_easy_width);   return stroker.createStroke(path); }

 

 

 

 

 

./CppQtExample35/qtarrowswidget.h

 


#ifndef QTARROWSWIDGET_H #define QTARROWSWIDGET_H #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include <QGraphicsView> #pragma GCC diagnostic pop struct QtArrowsWidget : public QGraphicsView {   QtArrowsWidget();   protected:   ///Respond to a key press   void keyPressEvent(QKeyEvent *event);   private:   ///The QGraphicsScene working on   QGraphicsScene * const m_scene; }; #endif // QTARROWSWIDGET_H

 

 

 

 

 

./CppQtExample35/qtarrowswidget.cpp

 


#include <cassert> #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 <QGraphicsPixmapItem> #include "qtarrowitem.h" #include "qtarrowswidget.h" #pragma GCC diagnostic pop QtArrowsWidget::QtArrowsWidget()   : m_scene(new QGraphicsScene(this)) {   this->setScene(m_scene);   const int n_arrows = 16;   for (int i=0; i!=n_arrows; ++i)   {     const double angle = 2.0 * boost::math::constants::pi<double>() * (static_cast<double>(i) / static_cast<double>(n_arrows));     const double d_angle = (2.0 * boost::math::constants::pi<double>()) / 32.0;     const double tail_x =  std::sin(angle) * 100.0;     const double tail_y = -std::cos(angle) * 100.0;     const bool tail = (std::rand() >> 4) % 2;     const double mid_x =  std::sin(angle + d_angle) * 150.0;     const double mid_y = -std::cos(angle + d_angle) * 150.0;     const double head_x =  std::sin(angle) * 200.0;     const double head_y = -std::cos(angle) * 200.0;     const bool head = (std::rand() >> 4) % 2;     QtArrowItem * item = new QtArrowItem(tail_x,tail_y,tail,mid_x,mid_y,head,head_x,head_y);     m_scene->addItem(item);   } } void QtArrowsWidget::keyPressEvent(QKeyEvent *event) {   const QList<QGraphicsItem *> v = m_scene->selectedItems();   std::for_each(v.begin(),v.end(),     [event](QGraphicsItem * item)     {       if (QtArrowItem * const arrow = dynamic_cast<QtArrowItem*>(item))       {         arrow->keyPressEvent(event);       }     }   ); }

 

 

 

 

 

./CppQtExample35/qtmain.cpp

 


#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include <QApplication> #include <QDesktopWidget> #include "qtarrowswidget.h" #pragma GCC diagnostic pop int main(int argc, char *argv[]) {   QApplication a(argc, argv);   QtArrowsWidget 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(); }