I want to present a widget which can be moved and at which it is possible to change the sizes. This widget can serve as the container for other widgets, such as to QLabel, QTableWidget and so on. This widget is used by me already in several projects. I hope it we will to you it is useful

mainwindow.h

  1. /*
  2. Programmer Aleksey Osipov
  3. email: aliks-os@yandex.ru
  4. */
  5.  
  6. #ifndef MAINWINDOW_H
  7. #define MAINWINDOW_H
  8.  
  9. #include <QMainWindow>
  10. #include "tcontainer.h"
  11.  
  12. namespace Ui {
  13. class MainWindow;
  14. }
  15.  
  16. class MainWindow : public QMainWindow
  17. {
  18.     Q_OBJECT
  19.     
  20. public:
  21.     explicit MainWindow(QWidget *parent = 0);
  22.     ~MainWindow();
  23.     
  24. private:
  25.     Ui::MainWindow *ui;
  26. };
  27.  
  28. #endif // MAINWINDOW_H

mainwindow.cpp

  1. /*
  2. Programmer Aleksey Osipov
  3. email: aliks-os@yandex.ru
  4. */
  5. #include "mainwindow.h"
  6. #include "ui_mainwindow.h"
  7.  
  8. MainWindow::MainWindow(QWidget *parent) :  QMainWindow(parent),  ui(new Ui::MainWindow) {
  9.     ui->setupUi(this);
  10.     this->showMaximized();
  11.     QLabel *lab1 = new QLabel("Label1");
  12.     QLabel *lab2 = new QLabel("Label2");
  13.     TContainer *con1 = new TContainer(this,QPoint(10,10),lab1);
  14.     TContainer *con2 = new TContainer(this,QPoint(20,50),lab2);
  15. }
  16.  
  17. MainWindow::~MainWindow() {
  18.     delete ui;
  19. }

tcontainer.h

  1. /*
  2. Programmer Aleksey Osipov
  3. email: aliks-os@yandex.ru
  4. */
  5. #ifndef TCONTAINER_H
  6. #define TCONTAINER_H
  7.  
  8. #include <QWidget>
  9. #include <QMouseEvent>
  10. #include <QtGui>
  11.  
  12. enum modes{
  13.     NONE = 0,
  14.     MOVE = 1,
  15.     RESIZETL = 2,
  16.     RESIZET = 3,
  17.     RESIZETR = 4,
  18.     RESIZER = 5,
  19.     RESIZEBR = 6,
  20.     RESIZEB = 7,
  21.     RESIZEBL = 8,
  22.     RESIZEL = 9
  23. };
  24.  
  25. class TContainer : public QWidget {
  26.     Q_OBJECT
  27. public:
  28.     TContainer(QWidget *parent, QPoint p, QWidget *cWidget = 0);
  29.     ~TContainer();
  30.     QWidget *childWidget;
  31.     QMenu *menu;
  32.     void setChildWidget(QWidget *cWidget);
  33.  
  34. protected:
  35.     int mode;
  36.     QPoint position;
  37.     QVBoxLayout* vLayout;
  38.     void setCursorShape(const QPoint &e_pos);
  39.     bool eventFilter( QObject *obj, QEvent *evt );
  40.     void keyPressEvent(QKeyEvent *);
  41.     void focusInEvent(QFocusEvent *);
  42.     void focusOutEvent(QFocusEvent *);
  43.     void mousePressEvent(QMouseEvent *);
  44.     void mouseReleaseEvent(QMouseEvent *);
  45.     void mouseMoveEvent(QMouseEvent *);
  46.     bool m_infocus;
  47.     bool m_showMenu;
  48.     bool m_isEditing;
  49.     void popupShow(const QPoint &pt);
  50.     QWidget *clone();
  51.  
  52. private:
  53.  
  54.  
  55. signals:
  56.     void inFocus(bool mode);
  57.     void outFocus(bool mode);
  58.     void newGeometry(QRect rect);
  59.  
  60. public slots:
  61.  
  62. };
  63.  
  64. #endif // TCONTAINER_H

tcontainer.cpp

  1. /*
  2. Programmer Aleksey Osipov
  3. email: aliks-os@yandex.ru
  4. */
  5.  
  6. #include "tcontainer.h"
  7.  
  8. TContainer::TContainer(QWidget *parent, QPoint p, QWidget *cWidget) : QWidget(parent) {
  9.     mode = NONE;
  10.     childWidget = cWidget;
  11.     setAttribute(Qt::WA_DeleteOnClose);
  12.     this->setVisible(true);
  13.     this->setAutoFillBackground(false);
  14.     this->setMouseTracking(true);
  15.     this->setFocusPolicy(Qt::ClickFocus);
  16.     this->setFocus();
  17.     this->move(p);
  18.  
  19.     vLayout = new QVBoxLayout(this);
  20.     if (cWidget != 0) {
  21.         cWidget->setParent(this);
  22.         cWidget->releaseMouse();
  23.         cWidget->setAttribute(Qt::WA_TransparentForMouseEvents, true);
  24.         vLayout->addWidget(cWidget);
  25.         vLayout->setContentsMargins(0,0,0,0);
  26.     }
  27.     this->setLayout(vLayout);
  28.  
  29.     m_infocus = true;
  30.     m_showMenu = false;
  31.     m_isEditing = true;
  32.     this->installEventFilter(parent);
  33. }
  34.  
  35. TContainer::~TContainer() {
  36.     delete vLayout;
  37. }
  38.  
  39. void TContainer::setChildWidget(QWidget *cWidget) {
  40.     if (cWidget != 0) {
  41.         childWidget = cWidget;
  42.         childWidget->setAttribute(Qt::WA_TransparentForMouseEvents, true);
  43.         childWidget->setParent(this);
  44.         vLayout->addWidget(cWidget);
  45.         vLayout->setContentsMargins(0,0,0,0);
  46.     }
  47. }
  48.  
  49. void TContainer::popupShow(const QPoint &pt) {
  50.     if (menu->isEmpty()) return;
  51.     QPoint global = this->mapToGlobal(pt);
  52.     m_showMenu = true;
  53.     menu->exec(global);
  54.     m_showMenu = false;
  55. }
  56.  
  57. void TContainer::focusInEvent(QFocusEvent *e) {
  58.     m_infocus = true;
  59.     this->parentWidget()->installEventFilter(this);
  60.     this->parentWidget()->repaint();
  61.     emit inFocus(true);
  62. }
  63.  
  64. void TContainer::focusOutEvent(QFocusEvent *e) {
  65.     if (!m_isEditing) return;
  66.     if (m_showMenu) return;
  67.     mode = NONE;
  68.     emit outFocus(false);
  69.     m_infocus = false;
  70. }
  71.  
  72. bool TContainer::eventFilter( QObject *obj, QEvent *evt ) {
  73.     //return QWidget::eventFilter(obj, evt);
  74.     if (m_infocus) {
  75.         QWidget *w = this->parentWidget();
  76.         if (w == obj && evt->type()==QEvent::Paint) {
  77.             //Рисуем выделение контейнара
  78.             QPainter painter(w);
  79.             QPoint p = this->mapTo(w,QPoint(-3,-3));
  80.             QPoint LT = w->mapFrom(w,p);
  81.             QPoint LB = w->mapFrom(w,QPoint(p.x(),p.y()+this->height()));
  82.             QPoint RB = w->mapFrom(w,QPoint(p.x()+this->width(),p.y()+this->height()));
  83.             QPoint RT = w->mapFrom(w,QPoint(p.x()+this->width(),p.y()));
  84.  
  85.             painter.fillRect(LT.x(),LT.y(),6,6,QColor("black"));
  86.             painter.fillRect(LB.x(),LB.y(),6,6,QColor("black"));
  87.             painter.fillRect(RB.x(),RB.y(),6,6,QColor("black"));
  88.             painter.fillRect(RT.x(),RT.y(),6,6,QColor("black"));
  89.             return QWidget::eventFilter(obj,evt);
  90.         }
  91.     }
  92.     return QWidget::eventFilter(obj, evt);}
  93.  
  94. void TContainer::mousePressEvent(QMouseEvent *e) {
  95.     position = QPoint(e->globalX()-geometry().x(), e->globalY()-geometry().y());
  96.     if (!m_isEditing) return;
  97.     if (!m_infocus) return;
  98.     //QWidget::mouseMoveEvent(e);
  99.     if (!e->buttons() & Qt::LeftButton) {
  100.         setCursorShape(e->pos());
  101.         return;
  102.     }
  103.     if(e->button()==Qt::RightButton) {
  104.         popupShow(e->pos());
  105.         e->accept();
  106.     }
  107. }
  108.  
  109. void TContainer::keyPressEvent(QKeyEvent *e) {
  110.     if (!m_isEditing) return;
  111.     if (e->key() == Qt::Key_Delete) {
  112.         this->deleteLater();
  113.     }
  114.     //Двигаем контайнер при помощи клавиш
  115.     if (QApplication::keyboardModifiers() == Qt::ControlModifier) {
  116.         QPoint newPos(this->x(),this->y());
  117.         if (e->key() == Qt::Key_Up) newPos.setY(newPos.y()-1);
  118.         if (e->key() == Qt::Key_Down) newPos.setY(newPos.y()+1);
  119.         if (e->key() == Qt::Key_Left) newPos.setX(newPos.x()-1);
  120.         if (e->key() == Qt::Key_Right) newPos.setX(newPos.x()+1);
  121.         move(newPos);
  122.     }
  123.     if (QApplication::keyboardModifiers() == Qt::ShiftModifier) {
  124.         if (e->key() == Qt::Key_Up) resize(width(),height()-1);
  125.         if (e->key() == Qt::Key_Down) resize(width(),height()+1);
  126.         if (e->key() == Qt::Key_Left) resize(width()-1,height());
  127.         if (e->key() == Qt::Key_Right) resize(width()+1,height());
  128.     }
  129.     emit newGeometry(this->geometry());
  130. }
  131.  
  132. void TContainer::setCursorShape(const QPoint &e_pos) {
  133.     const int diff = 3;
  134.     if (
  135.             //Left-Bottom
  136.             ((e_pos.y() > y() + height() - diff) &&          //Bottom
  137.              (e_pos.x() < x()+diff)) ||                      //Left
  138.             //Right-Bottom
  139.             ((e_pos.y() > y() + height() - diff) &&          //Bottom
  140.              (e_pos.x() > x() + width() - diff)) ||          //Right
  141.             //Left-Top
  142.             ((e_pos.y() < y() + diff) &&                     //Top
  143.              (e_pos.x() < x() + diff)) ||                    //Left
  144.             //Right-Top
  145.             ((e_pos.y() < y() + diff) &&                     //Top
  146.              (e_pos.x() > x() + width() - diff))             //Right
  147.        )
  148.     {
  149.         //Left-Bottom
  150.         if ((e_pos.y() > y() + height() - diff) &&           //Bottom
  151.             (e_pos.x() < x() + diff)) {                      //Left
  152.             mode = RESIZEBL;
  153.             setCursor(QCursor(Qt::SizeBDiagCursor));
  154.         }
  155.         //Right-Bottom
  156.         if ((e_pos.y() > y() + height() - diff) &&           //Bottom
  157.             (e_pos.x() > x() + width() - diff)) {            //Right
  158.             mode = RESIZEBR;
  159.             setCursor(QCursor(Qt::SizeFDiagCursor));
  160.         }
  161.         //Left-Top
  162.         if ((e_pos.y() < y() + diff) &&                      //Top
  163.             (e_pos.x() < x() + diff)) {                      //Left
  164.             mode = RESIZETL;
  165.             setCursor(QCursor(Qt::SizeFDiagCursor));
  166.         }
  167.         //Right-Top
  168.         if ((e_pos.y() < y() + diff) &&                      //Top
  169.             (e_pos.x() > x() + width() - diff)) {            //Right
  170.             mode = RESIZETR;
  171.             setCursor(QCursor(Qt::SizeBDiagCursor));
  172.         }
  173.     }
  174.     // проверка положения курсора по горизонтали
  175.     else if ((e_pos.x() < x() + diff) ||             //Left
  176.             ((e_pos.x() > x() + width() - diff))) {  //Right
  177.         if (e_pos.x() < x() + diff) {                //Left
  178.             setCursor(QCursor(Qt::SizeHorCursor));
  179.             mode = RESIZEL;
  180.         } else {                                     //Right
  181.             setCursor(QCursor(Qt::SizeHorCursor));
  182.             mode = RESIZER;
  183.         }
  184.     }
  185.     // проверка положения курсора по вертикали
  186.     else if (((e_pos.y() > y() + height() - diff)) || //Bottom
  187.               (e_pos.y() < y() + diff)) {             //Top
  188.         if (e_pos.y() < y() + diff) {                 //Top
  189.             setCursor(QCursor(Qt::SizeVerCursor));
  190.             mode = RESIZET;
  191.         } else {                                      //Bottom
  192.             setCursor(QCursor(Qt::SizeVerCursor));
  193.             mode = RESIZEB;
  194.         }
  195.     } else {
  196.         setCursor(QCursor(Qt::ArrowCursor));
  197.         mode = MOVE;
  198.     }
  199. }
  200.  
  201. void TContainer::mouseReleaseEvent(QMouseEvent *e) {
  202.     QWidget::mouseReleaseEvent(e);
  203. }
  204.  
  205. void TContainer::mouseMoveEvent(QMouseEvent *e) {
  206.     QWidget::mouseMoveEvent(e);
  207.     if (!m_isEditing) return;
  208.     if (!m_infocus) return;
  209.     if (!e->buttons() & Qt::LeftButton) {
  210.         QPoint p = QPoint(e->x()+geometry().x(), e->y()+geometry().y());
  211.         setCursorShape(p);
  212.         return;
  213.     }
  214.  
  215.     if ((mode == MOVE || mode == NONE) && e->buttons() && Qt::LeftButton) {
  216.         QPoint toMove = e->globalPos() - position;
  217.         if (toMove.x() < 0) return;
  218.         if (toMove.y() < 0) return;
  219.         if (toMove.x() > this->parentWidget()->width()-this->width()) return;
  220.         move(toMove);
  221.         emit newGeometry(this->geometry());
  222.         this->parentWidget()->repaint();
  223.         return;
  224.     }
  225.     if ((mode != MOVE) && e->buttons() && Qt::LeftButton) {
  226.         switch (mode){
  227.             case RESIZETL: {  //Left-Top
  228.                 int newwidth = e->globalX() - position.x() - geometry().x();
  229.                 int newheight = e->globalY() - position.y() - geometry().y();
  230.                 QPoint toMove = e->globalPos() - position;
  231.                 resize(this->geometry().width()-newwidth,this->geometry().height()-newheight);
  232.                 move(toMove.x(),toMove.y());
  233.                 break;
  234.             }
  235.             case RESIZETR: {  //Right-Top
  236.                 int newheight = e->globalY() - position.y() - geometry().y();
  237.                 QPoint toMove = e->globalPos() - position;
  238.                 resize(e->x(),this->geometry().height()-newheight);
  239.                 move(this->x(),toMove.y());
  240.                 break;
  241.             }
  242.             case RESIZEBL: {  //Left-Bottom
  243.                 int newwidth = e->globalX() - position.x() - geometry().x();
  244.                 QPoint toMove = e->globalPos() - position;
  245.                 resize(this->geometry().width()-newwidth,e->y());
  246.                 move(toMove.x(),this->y());
  247.                 break;
  248.             }
  249.             case RESIZEB: {   //Bottom
  250.                 resize(width(),e->y()); break;}
  251.             case RESIZEL:  {  //Left
  252.                 int newwidth = e->globalX() - position.x() - geometry().x();
  253.                 QPoint toMove = e->globalPos() - position;
  254.                 resize(this->geometry().width()-newwidth,height());
  255.                 move(toMove.x(),this->y());
  256.                 break;
  257.             }
  258.             case RESIZET:  {  //Top
  259.                 int newheight = e->globalY() - position.y() - geometry().y();
  260.                 QPoint toMove = e->globalPos() - position;
  261.                 resize(width(),this->geometry().height()-newheight);
  262.                 move(this->x(),toMove.y());
  263.                 break;
  264.             }
  265.             case RESIZER:  {  //Right
  266.                 resize(e->x(),height()); break;}
  267.             case RESIZEBR: {  //Right-Bottom
  268.                 resize(e->x(),e->y()); break;}
  269.         }
  270.         this->parentWidget()->repaint();
  271.     }
  272.     emit newGeometry(this->geometry());
  273.     //QWidget::mouseMoveEvent(e);
  274. }

Categories: