Difference between revisions of "Widget-moveable-and-resizeable"

From Qt Wiki
Jump to: navigation, search
Line 1: Line 1:
 
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
 
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<br /><code><br />/*<br />Programmer Aleksey Osipov<br />email: aliks-os</code>yandex.ru<br />*/
+
mainwindow.h
 +
<code>
 +
/*
 +
Programmer Aleksey Osipov
 +
email: aliks-os@yandex.ru
 +
*/
  
#ifndef MAINWINDOW_H<br />#define MAINWINDOW_H
+
#ifndef MAINWINDOW_H
 +
#define MAINWINDOW_H
  
#include &lt;QMainWindow&amp;gt;<br />#include &quot;tcontainer.h&amp;quot;
+
#include <QMainWindow>
 +
#include "tcontainer.h"
  
namespace Ui {<br />class MainWindow;<br />}
+
namespace Ui {
 +
class MainWindow;
 +
}
  
class MainWindow : public QMainWindow<br />{<br />    Q_OBJECT<br />    <br />public:<br />    explicit MainWindow(QWidget *parent = 0);<br />    ~MainWindow();<br />    <br />private:<br />    Ui::MainWindow '''ui;<br />};
+
class MainWindow : public QMainWindow
<br />#endif // MAINWINDOW_H
+
{
<br /><code><br />mainwindow.cpp
+
   Q_OBJECT
<br /></code><br />/'''<br />Programmer Aleksey Osipov<br />email: aliks-os<code>yandex.ru<br />*/<br />#include &quot;mainwindow.h&amp;quot;<br />#include &quot;ui_mainwindow.h&amp;quot;
+
   
 +
public:
 +
   explicit MainWindow(QWidget *parent = 0);
 +
   ~MainWindow();
 +
   
 +
private:
 +
   Ui::MainWindow '''ui;
 +
};
  
MainWindow::MainWindow(QWidget *parent) :  QMainWindow(parent),  ui(new Ui::MainWindow) {<br />    ui-&gt;setupUi(this);<br />    this-&gt;showMaximized();<br />    QLabel *lab1 = new QLabel(&quot;Label1&amp;quot;);<br />    QLabel *lab2 = new QLabel(&quot;Label2&amp;quot;);<br />    TContainer *con1 = new TContainer(this,QPoint(10,10),lab1);<br />    TContainer '''con2 = new TContainer(this,QPoint(20,50),lab2);<br />}
+
#endif // MAINWINDOW_H
<br />MainWindow::~MainWindow() {<br />    delete ui;<br />}<br /></code>
 
  
 +
</code>
 +
mainwindow.cpp
  
<br />tcontainer.h<br /><code><br />/'''<br />Programmer Aleksey Osipov<br />email: aliks-os</code>yandex.ru<br />*/<br />#ifndef TCONTAINER_H<br />#define TCONTAINER_H
+
<code>
 +
/'''
 +
Programmer Aleksey Osipov
 +
email: aliks-os@yandex.ru
 +
*/
 +
#include "mainwindow.h"
 +
#include "ui_mainwindow.h"
  
#include &lt;QWidget&amp;gt;<br />#include &lt;QMouseEvent&amp;gt;<br />#include &lt;QtGui&amp;gt;
+
MainWindow::MainWindow(QWidget *parent) :  QMainWindow(parent),  ui(new Ui::MainWindow) {
 +
   ui->setupUi(this);
 +
   this->showMaximized();
 +
   QLabel *lab1 = new QLabel("Label1");
 +
   QLabel *lab2 = new QLabel("Label2");
 +
   TContainer *con1 = new TContainer(this,QPoint(10,10),lab1);
 +
   TContainer '''con2 = new TContainer(this,QPoint(20,50),lab2);
 +
}
  
enum modes{<br />    NONE = 0,<br />    MOVE = 1,<br />    RESIZETL = 2,<br />    RESIZET = 3,<br />    RESIZETR = 4,<br />    RESIZER = 5,<br />    RESIZEBR = 6,<br />    RESIZEB = 7,<br />    RESIZEBL = 8,<br />    RESIZEL = 9<br />};
+
MainWindow::~MainWindow() {
 +
   delete ui;
 +
}
 +
</code>
  
class TContainer : public QWidget {<br />    Q_OBJECT<br />public:<br />    TContainer(QWidget *parent, QPoint p, QWidget *cWidget = 0);<br />    ~TContainer();<br />    QWidget *childWidget;<br />    QMenu *menu;<br />    void setChildWidget(QWidget '''cWidget);
 
<br />protected:<br />    int mode;<br />    QPoint position;<br />    QVBoxLayout''' vLayout;<br />    void setCursorShape(const QPoint &amp;e_pos);<br />    bool eventFilter( QObject *obj, QEvent '''evt );<br />    void keyPressEvent(QKeyEvent''');<br />    void focusInEvent(QFocusEvent ''');<br />    void focusOutEvent(QFocusEvent''');<br />    void mousePressEvent(QMouseEvent ''');<br />    void mouseReleaseEvent(QMouseEvent''');<br />    void mouseMoveEvent(QMouseEvent *);<br />    bool m_infocus;<br />    bool m_showMenu;<br />    bool m_isEditing;<br />    void popupShow(const QPoint &amp;pt);<br />    QWidget '''clone();
 
<br />private:
 
  
<br />signals:<br />    void inFocus(bool mode);<br />    void outFocus(bool mode);<br />    void newGeometry(QRect rect);
 
<br />public slots:
 
<br />};
 
<br />#endif // TCONTAINER_H
 
<br /><code>
 
  
<br />tcontainer.cpp
+
tcontainer.h
<br /></code><br />/'''<br />Programmer Aleksey Osipov<br />email: aliks-os<code>yandex.ru<br />*/
+
<code>
 +
/'''
 +
Programmer Aleksey Osipov
 +
email: aliks-os@yandex.ru
 +
*/
 +
#ifndef TCONTAINER_H
 +
#define TCONTAINER_H
  
#include &quot;tcontainer.h&amp;quot;
+
#include <QWidget>
 +
#include <QMouseEvent>
 +
#include <QtGui>
  
TContainer::TContainer(QWidget *parent, QPoint p, QWidget *cWidget) : QWidget(parent) {<br />    mode = NONE;<br />    childWidget = cWidget;<br />    setAttribute(Qt::WA_DeleteOnClose);<br />    this-&gt;setVisible(true);<br />    this-&gt;setAutoFillBackground(false);<br />    this-&gt;setMouseTracking(true);<br />    this-&gt;setFocusPolicy(Qt::ClickFocus);<br />    this-&gt;setFocus();<br />    this-&gt;move(p);
+
enum modes{
 +
   NONE = 0,
 +
   MOVE = 1,
 +
   RESIZETL = 2,
 +
   RESIZET = 3,
 +
   RESIZETR = 4,
 +
   RESIZER = 5,
 +
   RESIZEBR = 6,
 +
   RESIZEB = 7,
 +
   RESIZEBL = 8,
 +
   RESIZEL = 9
 +
};
  
   vLayout = new QVBoxLayout(this);<br />    if (cWidget != 0) {<br />        cWidget-&gt;setParent(this);<br />        cWidget-&gt;releaseMouse();<br />        cWidget-&gt;setAttribute(Qt::WA_TransparentForMouseEvents, true);<br />        vLayout-&gt;addWidget(cWidget);<br />        vLayout-&gt;setContentsMargins(0,0,0,0);<br />    }<br />    this-&gt;setLayout(vLayout);
+
class TContainer : public QWidget {
 +
   Q_OBJECT
 +
public:
 +
   TContainer(QWidget *parent, QPoint p, QWidget *cWidget = 0);
 +
   ~TContainer();
 +
   QWidget *childWidget;
 +
   QMenu *menu;
 +
   void setChildWidget(QWidget '''cWidget);
  
   m_infocus = true;<br />    m_showMenu = false;<br />    m_isEditing = true;<br />    this-&gt;installEventFilter(parent);<br />}
+
protected:
 +
   int mode;
 +
   QPoint position;
 +
   QVBoxLayout''' vLayout;
 +
   void setCursorShape(const QPoint &amp;e_pos);
 +
   bool eventFilter( QObject *obj, QEvent '''evt );
 +
   void keyPressEvent(QKeyEvent''');
 +
   void focusInEvent(QFocusEvent ''');
 +
   void focusOutEvent(QFocusEvent''');
 +
   void mousePressEvent(QMouseEvent ''');
 +
   void mouseReleaseEvent(QMouseEvent''');
 +
   void mouseMoveEvent(QMouseEvent *);
 +
   bool m_infocus;
 +
   bool m_showMenu;
 +
   bool m_isEditing;
 +
   void popupShow(const QPoint &amp;pt);
 +
   QWidget '''clone();
  
TContainer::~TContainer() {<br />    delete vLayout;<br />}
+
private:
  
void TContainer::setChildWidget(QWidget *cWidget) {<br />    if (cWidget != 0) {<br />        childWidget = cWidget;<br />        childWidget-&gt;setAttribute(Qt::WA_TransparentForMouseEvents, true);<br />        childWidget-&gt;setParent(this);<br />        vLayout-&gt;addWidget(cWidget);<br />        vLayout-&gt;setContentsMargins(0,0,0,0);<br />    }<br />}
 
  
void TContainer::popupShow(const QPoint &amp;pt) {<br />    if (menu-&gt;isEmpty()) return;<br />    QPoint global = this-&gt;mapToGlobal(pt);<br />    m_showMenu = true;<br />    menu-&gt;exec&amp;amp;#40;global&amp;amp;#41;;<br />    m_showMenu = false;<br />}
+
signals:
 +
   void inFocus(bool mode);
 +
   void outFocus(bool mode);
 +
   void newGeometry(QRect rect);
  
void TContainer::focusInEvent(QFocusEvent *e) {<br />    m_infocus = true;<br />    this-&gt;parentWidget()<s>&gt;installEventFilter(this);<br />    this</s>&gt;parentWidget()<s>&gt;repaint();<br />    emit inFocus(true);<br />}
+
public slots:
<br />void TContainer::focusOutEvent(QFocusEvent *e) {<br />    if (!m_isEditing) return;<br />    if (m_showMenu) return;<br />    mode = NONE;<br />    emit outFocus(false);<br />    m_infocus = false;<br />}
 
<br />bool TContainer::eventFilter( QObject *obj, QEvent *evt ) {<br />    //return QWidget::eventFilter(obj, evt);<br />    if (m_infocus) {<br />        QWidget *w = this</s>&gt;parentWidget();<br />        if (w  obj &amp;amp;&amp;amp; evt-&amp;gt;type()QEvent::Paint) {<br />            //Рисуем выделение контейнара<br />            QPainter painter(w);<br />            QPoint p = this-&gt;mapTo(w,QPoint(–3,<s>3));<br />            QPoint LT = w</s>&gt;mapFrom(w,p);<br />            QPoint LB = w-&gt;mapFrom(w,QPoint(p.x(),p.y()+this-&gt;height()));<br />            QPoint RB = w-&gt;mapFrom(w,QPoint(p.x()+this-&gt;width(),p.y()+this-&gt;height()));<br />            QPoint RT = w-&gt;mapFrom(w,QPoint(p.x()+this-&gt;width(),p.y()));
 
  
           painter.fillRect(LT.x(),LT.y(),6,6,QColor(&quot;black&amp;quot;));<br />            painter.fillRect(LB.x(),LB.y(),6,6,QColor(&quot;black&amp;quot;));<br />            painter.fillRect(RB.x(),RB.y(),6,6,QColor(&quot;black&amp;quot;));<br />            painter.fillRect(RT.x(),RT.y(),6,6,QColor(&quot;black&amp;quot;));<br />            return QWidget::eventFilter(obj,evt);<br />        }<br />    }<br />    return QWidget::eventFilter(obj, evt);}
+
};
  
void TContainer::mousePressEvent(QMouseEvent *e) {<br />    position = QPoint(e-&gt;globalX()<s>geometry().x(), e</s>&gt;globalY()<s>geometry().y());<br />    if (!m_isEditing) return;<br />    if (!m_infocus) return;<br />    //QWidget::mouseMoveEvent(e);<br />    if (!e</s>&gt;buttons() &amp; Qt::LeftButton) {<br />        setCursorShape(e-&gt;pos());<br />        return;<br />    }<br />    if(e-&gt;button()==Qt::RightButton) {<br />        popupShow(e-&gt;pos());<br />        e-&gt;accept();<br />    }<br />}
+
#endif // TCONTAINER_H
  
void TContainer::keyPressEvent(QKeyEvent *e) {<br />    if (!m_isEditing) return;<br />    if (e-&gt;key()  Qt::Key_Delete) &amp;#123;
+
</code>
         this-&amp;gt;deleteLater();
+
 
     &amp;#125;
+
 
 +
tcontainer.cpp
 +
 
 +
<code>
 +
/'''
 +
Programmer Aleksey Osipov
 +
email: aliks-os@yandex.ru
 +
*/
 +
 
 +
#include "tcontainer.h"
 +
 
 +
TContainer::TContainer(QWidget *parent, QPoint p, QWidget *cWidget) : QWidget(parent) {
 +
   mode = NONE;
 +
   childWidget = cWidget;
 +
   setAttribute(Qt::WA_DeleteOnClose);
 +
   this->setVisible(true);
 +
   this->setAutoFillBackground(false);
 +
   this->setMouseTracking(true);
 +
   this->setFocusPolicy(Qt::ClickFocus);
 +
   this->setFocus();
 +
   this->move(p);
 +
 
 +
   vLayout = new QVBoxLayout(this);
 +
   if (cWidget != 0) {
 +
       cWidget->setParent(this);
 +
       cWidget->releaseMouse();
 +
       cWidget->setAttribute(Qt::WA_TransparentForMouseEvents, true);
 +
       vLayout->addWidget(cWidget);
 +
       vLayout->setContentsMargins(0,0,0,0);
 +
   }
 +
   this->setLayout(vLayout);
 +
 
 +
   m_infocus = true;
 +
   m_showMenu = false;
 +
   m_isEditing = true;
 +
   this->installEventFilter(parent);
 +
}
 +
 
 +
TContainer::~TContainer() {
 +
   delete vLayout;
 +
}
 +
 
 +
void TContainer::setChildWidget(QWidget *cWidget) {
 +
   if (cWidget != 0) {
 +
       childWidget = cWidget;
 +
       childWidget->setAttribute(Qt::WA_TransparentForMouseEvents, true);
 +
       childWidget->setParent(this);
 +
       vLayout->addWidget(cWidget);
 +
       vLayout->setContentsMargins(0,0,0,0);
 +
   }
 +
}
 +
 
 +
void TContainer::popupShow(const QPoint &amp;pt) {
 +
   if (menu->isEmpty()) return;
 +
   QPoint global = this->mapToGlobal(pt);
 +
   m_showMenu = true;
 +
   menu->exec(global);
 +
   m_showMenu = false;
 +
}
 +
 
 +
void TContainer::focusInEvent(QFocusEvent *e) {
 +
   m_infocus = true;
 +
   this->parentWidget()->installEventFilter(this);
 +
   this->parentWidget()->repaint();
 +
   emit inFocus(true);
 +
}
 +
 
 +
void TContainer::focusOutEvent(QFocusEvent *e) {
 +
   if (!m_isEditing) return;
 +
   if (m_showMenu) return;
 +
   mode = NONE;
 +
   emit outFocus(false);
 +
   m_infocus = false;
 +
}
 +
 
 +
bool TContainer::eventFilter( QObject *obj, QEvent *evt ) {
 +
   //return QWidget::eventFilter(obj, evt);
 +
   if (m_infocus) {
 +
       QWidget *w = this->parentWidget();
 +
       if (w  obj &amp;amp;&amp;amp; evt->type()QEvent::Paint) {
 +
           //Рисуем выделение контейнара
 +
           QPainter painter(w);
 +
           QPoint p = this->mapTo(w,QPoint(–3,-3));
 +
           QPoint LT = w->mapFrom(w,p);
 +
           QPoint LB = w->mapFrom(w,QPoint(p.x(),p.y()+this->height()));
 +
           QPoint RB = w->mapFrom(w,QPoint(p.x()+this->width(),p.y()+this->height()));
 +
           QPoint RT = w->mapFrom(w,QPoint(p.x()+this->width(),p.y()));
 +
 
 +
           painter.fillRect(LT.x(),LT.y(),6,6,QColor("black"));
 +
           painter.fillRect(LB.x(),LB.y(),6,6,QColor("black"));
 +
           painter.fillRect(RB.x(),RB.y(),6,6,QColor("black"));
 +
           painter.fillRect(RT.x(),RT.y(),6,6,QColor("black"));
 +
           return QWidget::eventFilter(obj,evt);
 +
       }
 +
   }
 +
   return QWidget::eventFilter(obj, evt);}
 +
 
 +
void TContainer::mousePressEvent(QMouseEvent *e) {
 +
   position = QPoint(e->globalX()-geometry().x(), e->globalY()-geometry().y());
 +
   if (!m_isEditing) return;
 +
   if (!m_infocus) return;
 +
     //QWidget::mouseMoveEvent(e);
 +
   if (!e->buttons() &amp; Qt::LeftButton) {
 +
       setCursorShape(e->pos());
 +
       return;
 +
   }
 +
   if(e->button()==Qt::RightButton) {
 +
         popupShow(e->pos());
 +
       e->accept();
 +
   }
 +
}
 +
 
 +
void TContainer::keyPressEvent(QKeyEvent *e) {
 +
   if (!m_isEditing) return;
 +
   if (e->key()  Qt::Key_Delete) {
 +
       this->deleteLater();
 +
     }
 
     //Двигаем контайнер при помощи клавиш
 
     //Двигаем контайнер при помощи клавиш
     if (QApplication::keyboardModifiers()  Qt::ControlModifier) {<br />        QPoint newPos(this-&gt;x(),this-&gt;y());<br />        if (e-&gt;key()  Qt::Key_Up) newPos.setY(newPos.y()-1);
+
     if (QApplication::keyboardModifiers()  Qt::ControlModifier) {
         if (e-&amp;gt;key()  Qt::Key_Down) newPos.setY(newPos.y()+1);<br />        if (e-&gt;key()  Qt::Key_Left) newPos.setX(newPos.x()-1);
+
       QPoint newPos(this->x(),this->y());
         if (e-&amp;gt;key()  Qt::Key_Right) newPos.setX(newPos.x()+1);<br />        move(newPos);<br />    }<br />    if (QApplication::keyboardModifiers()  Qt::ShiftModifier) &amp;#123;
+
       if (e->key()  Qt::Key_Up) newPos.setY(newPos.y()-1);
         if (e-&amp;gt;key()  Qt::Key_Up) resize(width(),height()<s>1);<br />        if (e</s>&gt;key()  Qt::Key_Down) resize(width(),height()+1);
+
         if (e->key()  Qt::Key_Down) newPos.setY(newPos.y()+1);
         if (e-&amp;gt;key()  Qt::Key_Left) resize(width()<s>1,height());<br />        if (e</s>&gt;key() == Qt::Key_Right) resize(width()''1,height());<br />    }<br />    emit newGeometry(this-&gt;geometry());<br />}
+
       if (e->key()  Qt::Key_Left) newPos.setX(newPos.x()-1);
<br />void TContainer::setCursorShape(const QPoint &amp;e_pos) {<br />    const int diff = 3;<br />    if (<br />            //Left-Bottom<br />            ((e_pos.y() &gt; y()'' height() - diff) &amp;&amp;          //Bottom<br />             (e_pos.x() &lt; x()''diff)) ||                      //Left<br />            //Right-Bottom<br />            ((e_pos.y() &gt; y()'' height() - diff) &amp;&amp;          //Bottom<br />             (e_pos.x() &gt; x() + width() - diff)) ||          //Right<br />            //Left-Top<br />            ((e_pos.y() &lt; y() + diff) &amp;&amp;                     //Top<br />             (e_pos.x() &lt; x() + diff)) ||                    //Left<br />            //Right-Top<br />            ((e_pos.y() &lt; y() + diff) &amp;&amp;                     //Top<br />             (e_pos.x() &gt; x() + width() - diff))             //Right<br />       )<br />    {<br />        //Left-Bottom<br />        if ((e_pos.y() &gt; y() + height() - diff) &amp;&amp;           //Bottom<br />            (e_pos.x() &lt; x() + diff)) {                      //Left<br />            mode = RESIZEBL;<br />            setCursor(QCursor(Qt::SizeBDiagCursor));<br />        }<br />        //Right-Bottom<br />        if ((e_pos.y() &gt; y() + height() - diff) &amp;&amp;           //Bottom<br />            (e_pos.x() &gt; x() + width() - diff)) {            //Right<br />            mode = RESIZEBR;<br />            setCursor(QCursor(Qt::SizeFDiagCursor));<br />        }<br />        //Left-Top<br />        if ((e_pos.y() &lt; y() + diff) &amp;&amp;                      //Top<br />            (e_pos.x() &lt; x() + diff)) {                      //Left<br />            mode = RESIZETL;<br />            setCursor(QCursor(Qt::SizeFDiagCursor));<br />        }<br />        //Right-Top<br />        if ((e_pos.y() &lt; y() + diff) &amp;&amp;                      //Top<br />            (e_pos.x() &gt; x() + width() - diff)) {            //Right<br />            mode = RESIZETR;<br />            setCursor(QCursor(Qt::SizeBDiagCursor));<br />        }<br />    }<br />    // проверка положения курсора по горизонтали<br />    else if ((e_pos.x() &lt; x() + diff) ||             //Left<br />            ((e_pos.x() &gt; x() + width() - diff))) {  //Right<br />        if (e_pos.x() &lt; x() + diff) {                //Left<br />            setCursor(QCursor(Qt::SizeHorCursor));<br />            mode = RESIZEL;<br />        } else {                                     //Right<br />            setCursor(QCursor(Qt::SizeHorCursor));<br />            mode = RESIZER;<br />        }<br />    }<br />    // проверка положения курсора по вертикали<br />    else if (((e_pos.y() &gt; y() + height() - diff)) || //Bottom<br />              (e_pos.y() &lt; y() + diff)) {             //Top<br />        if (e_pos.y() &lt; y() + diff) {                 //Top<br />            setCursor(QCursor(Qt::SizeVerCursor));<br />            mode = RESIZET;<br />        } else {                                      //Bottom<br />            setCursor(QCursor(Qt::SizeVerCursor));<br />            mode = RESIZEB;<br />        }<br />    } else {<br />        setCursor(QCursor(Qt::ArrowCursor));<br />        mode = MOVE;<br />    }<br />}
+
         if (e->key()  Qt::Key_Right) newPos.setX(newPos.x()+1);
 +
       move(newPos);
 +
   }
 +
   if (QApplication::keyboardModifiers()  Qt::ShiftModifier) {
 +
         if (e->key()  Qt::Key_Up) resize(width(),height()-1);
 +
       if (e->key()  Qt::Key_Down) resize(width(),height()+1);
 +
         if (e->key()  Qt::Key_Left) resize(width()-1,height());
 +
       if (e->key() == Qt::Key_Right) resize(width()''1,height());
 +
   }
 +
   emit newGeometry(this->geometry());
 +
}
 +
 
 +
void TContainer::setCursorShape(const QPoint &amp;e_pos) {
 +
   const int diff = 3;
 +
   if (
 +
           //Left-Bottom
 +
           ((e_pos.y() > y()'' height() - diff) &amp;&amp;          //Bottom
 +
            (e_pos.x() < x()''diff)) ||                      //Left
 +
           //Right-Bottom
 +
           ((e_pos.y() > y()'' height() - diff) &amp;&amp;          //Bottom
 +
            (e_pos.x() > x() + width() - diff)) ||          //Right
 +
           //Left-Top
 +
           ((e_pos.y() < y() + diff) &amp;&amp;                     //Top
 +
            (e_pos.x() < x() + diff)) ||                    //Left
 +
           //Right-Top
 +
           ((e_pos.y() < y() + diff) &amp;&amp;                     //Top
 +
            (e_pos.x() > x() + width() - diff))             //Right
 +
      )
 +
   {
 +
       //Left-Bottom
 +
       if ((e_pos.y() > y() + height() - diff) &amp;&amp;           //Bottom
 +
           (e_pos.x() < x() + diff)) {                      //Left
 +
           mode = RESIZEBL;
 +
           setCursor(QCursor(Qt::SizeBDiagCursor));
 +
       }
 +
       //Right-Bottom
 +
       if ((e_pos.y() > y() + height() - diff) &amp;&amp;           //Bottom
 +
           (e_pos.x() > x() + width() - diff)) {            //Right
 +
           mode = RESIZEBR;
 +
           setCursor(QCursor(Qt::SizeFDiagCursor));
 +
       }
 +
       //Left-Top
 +
       if ((e_pos.y() < y() + diff) &amp;&amp;                      //Top
 +
           (e_pos.x() < x() + diff)) {                      //Left
 +
           mode = RESIZETL;
 +
           setCursor(QCursor(Qt::SizeFDiagCursor));
 +
       }
 +
       //Right-Top
 +
       if ((e_pos.y() < y() + diff) &amp;&amp;                      //Top
 +
           (e_pos.x() > x() + width() - diff)) {            //Right
 +
           mode = RESIZETR;
 +
           setCursor(QCursor(Qt::SizeBDiagCursor));
 +
       }
 +
   }
 +
   // проверка положения курсора по горизонтали
 +
   else if ((e_pos.x() < x() + diff) ||             //Left
 +
           ((e_pos.x() > x() + width() - diff))) {  //Right
 +
       if (e_pos.x() < x() + diff) {                //Left
 +
           setCursor(QCursor(Qt::SizeHorCursor));
 +
           mode = RESIZEL;
 +
       } else {                                     //Right
 +
           setCursor(QCursor(Qt::SizeHorCursor));
 +
           mode = RESIZER;
 +
       }
 +
   }
 +
   // проверка положения курсора по вертикали
 +
   else if (((e_pos.y() > y() + height() - diff)) || //Bottom
 +
             (e_pos.y() < y() + diff)) {             //Top
 +
       if (e_pos.y() < y() + diff) {                 //Top
 +
           setCursor(QCursor(Qt::SizeVerCursor));
 +
           mode = RESIZET;
 +
       } else {                                      //Bottom
 +
           setCursor(QCursor(Qt::SizeVerCursor));
 +
           mode = RESIZEB;
 +
       }
 +
   } else {
 +
       setCursor(QCursor(Qt::ArrowCursor));
 +
       mode = MOVE;
 +
   }
 +
}
  
void TContainer::mouseReleaseEvent(QMouseEvent *e) {<br />    QWidget::mouseReleaseEvent(e);<br />}
+
void TContainer::mouseReleaseEvent(QMouseEvent *e) {
 +
   QWidget::mouseReleaseEvent(e);
 +
}
  
void TContainer::mouseMoveEvent(QMouseEvent *e) {<br />    QWidget::mouseMoveEvent(e);<br />    if (!m_isEditing) return;<br />    if (!m_infocus) return;<br />    if (!e-&gt;buttons() &amp; Qt::LeftButton) {<br />        QPoint p = QPoint(e-&gt;x()+geometry().x(), e-&gt;y()+geometry().y());<br />        setCursorShape(p);<br />        return;<br />    }
+
void TContainer::mouseMoveEvent(QMouseEvent *e) {
 +
   QWidget::mouseMoveEvent(e);
 +
   if (!m_isEditing) return;
 +
   if (!m_infocus) return;
 +
   if (!e->buttons() &amp; Qt::LeftButton) {
 +
       QPoint p = QPoint(e->x()+geometry().x(), e->y()+geometry().y());
 +
       setCursorShape(p);
 +
       return;
 +
   }
  
   if ((mode  MOVE || mode  NONE) &amp;&amp; e-&gt;buttons() &amp;&amp; Qt::LeftButton) {<br />        QPoint toMove = e-&gt;globalPos() - position;<br />        if (toMove.x() &lt; 0) return;<br />        if (toMove.y() &lt; 0) return;<br />        if (toMove.x() &gt; this-&gt;parentWidget()-&gt;width()<s>this</s>&gt;width()) return;<br />        move(toMove);<br />        emit newGeometry(this-&gt;geometry());<br />        this-&gt;parentWidget()<s>&gt;repaint();<br />        return;<br />    }<br />    if ((mode != MOVE) &amp;&amp; e</s>&gt;buttons() &amp;&amp; Qt::LeftButton) {<br />        switch (mode){<br />            case RESIZETL: {  //Left-Top<br />                int newwidth = e-&gt;globalX() - position.x() - geometry().x();<br />                int newheight = e-&gt;globalY() - position.y() - geometry().y();<br />                QPoint toMove = e-&gt;globalPos() - position;<br />                resize(this-&gt;geometry().width()<s>newwidth,this</s>&gt;geometry().height()<s>newheight);<br />                move(toMove.x(),toMove.y());<br />                break;<br />            }<br />            case RESIZETR: {  //Right-Top<br />                int newheight = e</s>&gt;globalY() - position.y() - geometry().y();<br />                QPoint toMove = e-&gt;globalPos() - position;<br />                resize(e-&gt;x(),this-&gt;geometry().height()<s>newheight);<br />                move(this</s>&gt;x(),toMove.y());<br />                break;<br />            }<br />            case RESIZEBL: {  //Left-Bottom<br />                int newwidth = e-&gt;globalX() - position.x() - geometry().x();<br />                QPoint toMove = e-&gt;globalPos() - position;<br />                resize(this-&gt;geometry().width()<s>newwidth,e</s>&gt;y());<br />                move(toMove.x(),this-&gt;y());<br />                break;<br />            }<br />            case RESIZEB: {   //Bottom<br />                resize(width(),e-&gt;y()); break;}<br />            case RESIZEL:  {  //Left<br />                int newwidth = e-&gt;globalX() - position.x() - geometry().x();<br />                QPoint toMove = e-&gt;globalPos() - position;<br />                resize(this-&gt;geometry().width()<s>newwidth,height());<br />                move(toMove.x(),this</s>&gt;y());<br />                break;<br />            }<br />            case RESIZET:  {  //Top<br />                int newheight = e-&gt;globalY() - position.y() - geometry().y();<br />                QPoint toMove = e-&gt;globalPos() - position;<br />                resize(width(),this-&gt;geometry().height()<s>newheight);<br />                move(this</s>&gt;x(),toMove.y());<br />                break;<br />            }<br />            case RESIZER:  {  //Right<br />                resize(e-&gt;x(),height()); break;}<br />            case RESIZEBR: {  //Right-Bottom<br />                resize(e-&gt;x(),e-&gt;y()); break;}<br />        }<br />        this-&gt;parentWidget()<s>&gt;repaint();<br />    }<br />    emit newGeometry(this</s>&gt;geometry());<br />    //QWidget::mouseMoveEvent(e);<br />}<br /></code>
+
   if ((mode  MOVE || mode  NONE) &amp;&amp; e->buttons() &amp;&amp; Qt::LeftButton) {
 +
       QPoint toMove = e->globalPos() - position;
 +
       if (toMove.x() < 0) return;
 +
       if (toMove.y() < 0) return;
 +
       if (toMove.x() > this->parentWidget()->width()-this->width()) return;
 +
       move(toMove);
 +
       emit newGeometry(this->geometry());
 +
       this->parentWidget()->repaint();
 +
       return;
 +
   }
 +
   if ((mode != MOVE) &amp;&amp; e->buttons() &amp;&amp; Qt::LeftButton) {
 +
       switch (mode){
 +
           case RESIZETL: {  //Left-Top
 +
               int newwidth = e->globalX() - position.x() - geometry().x();
 +
               int newheight = e->globalY() - position.y() - geometry().y();
 +
               QPoint toMove = e->globalPos() - position;
 +
               resize(this->geometry().width()-newwidth,this->geometry().height()-newheight);
 +
               move(toMove.x(),toMove.y());
 +
               break;
 +
           }
 +
           case RESIZETR: {  //Right-Top
 +
               int newheight = e->globalY() - position.y() - geometry().y();
 +
               QPoint toMove = e->globalPos() - position;
 +
               resize(e->x(),this->geometry().height()-newheight);
 +
               move(this->x(),toMove.y());
 +
               break;
 +
           }
 +
           case RESIZEBL: {  //Left-Bottom
 +
               int newwidth = e->globalX() - position.x() - geometry().x();
 +
               QPoint toMove = e->globalPos() - position;
 +
               resize(this->geometry().width()-newwidth,e->y());
 +
               move(toMove.x(),this->y());
 +
               break;
 +
           }
 +
           case RESIZEB: {   //Bottom
 +
               resize(width(),e->y()); break;}
 +
           case RESIZEL:  {  //Left
 +
               int newwidth = e->globalX() - position.x() - geometry().x();
 +
               QPoint toMove = e->globalPos() - position;
 +
               resize(this->geometry().width()-newwidth,height());
 +
               move(toMove.x(),this->y());
 +
               break;
 +
           }
 +
           case RESIZET:  {  //Top
 +
               int newheight = e->globalY() - position.y() - geometry().y();
 +
               QPoint toMove = e->globalPos() - position;
 +
               resize(width(),this->geometry().height()-newheight);
 +
               move(this->x(),toMove.y());
 +
               break;
 +
           }
 +
           case RESIZER:  {  //Right
 +
               resize(e->x(),height()); break;}
 +
           case RESIZEBR: {  //Right-Bottom
 +
               resize(e->x(),e->y()); break;}
 +
       }
 +
       this->parentWidget()->repaint();
 +
   }
 +
   emit newGeometry(this->geometry());
 +
   //QWidget::mouseMoveEvent(e);
 +
}
 +
</code>

Revision as of 09:59, 25 February 2015

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 /* Programmer Aleksey Osipov email: aliks-os@yandex.ru

  • /
  1. ifndef MAINWINDOW_H
  2. define MAINWINDOW_H
  1. include <QMainWindow>
  2. include "tcontainer.h"

namespace Ui { class MainWindow; }

class MainWindow : public QMainWindow {

   Q_OBJECT
   

public:

   explicit MainWindow(QWidget *parent = 0);
   ~MainWindow();
   

private:

   Ui::MainWindow ui;

};

  1. endif // MAINWINDOW_H

mainwindow.cpp

/ Programmer Aleksey Osipov email: aliks-os@yandex.ru

  • /
  1. include "mainwindow.h"
  2. include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :  QMainWindow(parent),  ui(new Ui::MainWindow) {

   ui->setupUi(this);
   this->showMaximized();
   QLabel *lab1 = new QLabel("Label1");
   QLabel *lab2 = new QLabel("Label2");
   TContainer *con1 = new TContainer(this,QPoint(10,10),lab1);
   TContainer con2 = new TContainer(this,QPoint(20,50),lab2);

}

MainWindow::~MainWindow() {

   delete ui;

}


tcontainer.h / Programmer Aleksey Osipov email: aliks-os@yandex.ru

  • /
  1. ifndef TCONTAINER_H
  2. define TCONTAINER_H
  1. include <QWidget>
  2. include <QMouseEvent>
  3. include <QtGui>

enum modes{

   NONE = 0,
   MOVE = 1,
   RESIZETL = 2,
   RESIZET = 3,
   RESIZETR = 4,
   RESIZER = 5,
   RESIZEBR = 6,
   RESIZEB = 7,
   RESIZEBL = 8,
   RESIZEL = 9

};

class TContainer : public QWidget {

   Q_OBJECT

public:

   TContainer(QWidget *parent, QPoint p, QWidget *cWidget = 0);
   ~TContainer();
   QWidget *childWidget;
   QMenu *menu;
   void setChildWidget(QWidget cWidget);

protected:

   int mode;
   QPoint position;
   QVBoxLayout vLayout;
   void setCursorShape(const QPoint &e_pos);
   bool eventFilter( QObject *obj, QEvent evt );
   void keyPressEvent(QKeyEvent);
   void focusInEvent(QFocusEvent );
   void focusOutEvent(QFocusEvent);
   void mousePressEvent(QMouseEvent );
   void mouseReleaseEvent(QMouseEvent);
   void mouseMoveEvent(QMouseEvent *);
   bool m_infocus;
   bool m_showMenu;
   bool m_isEditing;
   void popupShow(const QPoint &pt);
   QWidget clone();

private:


signals:

   void inFocus(bool mode);
   void outFocus(bool mode);
   void newGeometry(QRect rect);

public slots:

};

  1. endif // TCONTAINER_H


tcontainer.cpp

/ Programmer Aleksey Osipov email: aliks-os@yandex.ru

  • /
  1. include "tcontainer.h"

TContainer::TContainer(QWidget *parent, QPoint p, QWidget *cWidget) : QWidget(parent) {

   mode = NONE;
   childWidget = cWidget;
   setAttribute(Qt::WA_DeleteOnClose);
   this->setVisible(true);
   this->setAutoFillBackground(false);
   this->setMouseTracking(true);
   this->setFocusPolicy(Qt::ClickFocus);
   this->setFocus();
   this->move(p);

   vLayout = new QVBoxLayout(this);

   if (cWidget != 0) {
       cWidget->setParent(this);
       cWidget->releaseMouse();
       cWidget->setAttribute(Qt::WA_TransparentForMouseEvents, true);
       vLayout->addWidget(cWidget);
       vLayout->setContentsMargins(0,0,0,0);
   }
   this->setLayout(vLayout);

   m_infocus = true;

   m_showMenu = false;
   m_isEditing = true;
   this->installEventFilter(parent);

}

TContainer::~TContainer() {

   delete vLayout;

}

void TContainer::setChildWidget(QWidget *cWidget) {

   if (cWidget != 0) {
       childWidget = cWidget;
       childWidget->setAttribute(Qt::WA_TransparentForMouseEvents, true);
       childWidget->setParent(this);
       vLayout->addWidget(cWidget);
       vLayout->setContentsMargins(0,0,0,0);
   }

}

void TContainer::popupShow(const QPoint &pt) {

   if (menu->isEmpty()) return;
   QPoint global = this->mapToGlobal(pt);
   m_showMenu = true;
   menu->exec(global);
   m_showMenu = false;

}

void TContainer::focusInEvent(QFocusEvent *e) {

   m_infocus = true;
   this->parentWidget()->installEventFilter(this);
   this->parentWidget()->repaint();
   emit inFocus(true);

}

void TContainer::focusOutEvent(QFocusEvent *e) {

   if (!m_isEditing) return;
   if (m_showMenu) return;
   mode = NONE;
   emit outFocus(false);
   m_infocus = false;

}

bool TContainer::eventFilter( QObject *obj, QEvent *evt ) {

   //return QWidget::eventFilter(obj, evt);
   if (m_infocus) {
       QWidget *w = this->parentWidget();
       if (w  obj &amp;&amp; evt->type()QEvent::Paint) {
           //Рисуем выделение контейнара
           QPainter painter(w);
           QPoint p = this->mapTo(w,QPoint(–3,-3));
           QPoint LT = w->mapFrom(w,p);
           QPoint LB = w->mapFrom(w,QPoint(p.x(),p.y()+this->height()));
           QPoint RB = w->mapFrom(w,QPoint(p.x()+this->width(),p.y()+this->height()));
           QPoint RT = w->mapFrom(w,QPoint(p.x()+this->width(),p.y()));

           painter.fillRect(LT.x(),LT.y(),6,6,QColor("black"));

           painter.fillRect(LB.x(),LB.y(),6,6,QColor("black"));
           painter.fillRect(RB.x(),RB.y(),6,6,QColor("black"));
           painter.fillRect(RT.x(),RT.y(),6,6,QColor("black"));
           return QWidget::eventFilter(obj,evt);
       }
   }
   return QWidget::eventFilter(obj, evt);}

void TContainer::mousePressEvent(QMouseEvent *e) {

   position = QPoint(e->globalX()-geometry().x(), e->globalY()-geometry().y());
   if (!m_isEditing) return;
   if (!m_infocus) return;
   //QWidget::mouseMoveEvent(e);
   if (!e->buttons() & Qt::LeftButton) {
       setCursorShape(e->pos());
       return;
   }
   if(e->button()==Qt::RightButton) {
       popupShow(e->pos());
       e->accept();
   }

}

void TContainer::keyPressEvent(QKeyEvent *e) {

   if (!m_isEditing) return;
   if (e->key()  Qt::Key_Delete) {
       this->deleteLater();
   }
   //Двигаем контайнер при помощи клавиш
   if (QApplication::keyboardModifiers()  Qt::ControlModifier) {
       QPoint newPos(this->x(),this->y());
       if (e->key()  Qt::Key_Up) newPos.setY(newPos.y()-1);
       if (e->key()  Qt::Key_Down) newPos.setY(newPos.y()+1);
       if (e->key()  Qt::Key_Left) newPos.setX(newPos.x()-1);
       if (e->key()  Qt::Key_Right) newPos.setX(newPos.x()+1);
       move(newPos);
   }
   if (QApplication::keyboardModifiers()  Qt::ShiftModifier) {
       if (e->key()  Qt::Key_Up) resize(width(),height()-1);
       if (e->key()  Qt::Key_Down) resize(width(),height()+1);
       if (e->key()  Qt::Key_Left) resize(width()-1,height());
       if (e->key() == Qt::Key_Right) resize(width()1,height());
   }
   emit newGeometry(this->geometry());

}

void TContainer::setCursorShape(const QPoint &e_pos) {

   const int diff = 3;
   if (
           //Left-Bottom
           ((e_pos.y() > y() height() - diff) &&          //Bottom
            (e_pos.x() < x()diff)) ||                      //Left
           //Right-Bottom
           ((e_pos.y() > y() height() - diff) &&          //Bottom
            (e_pos.x() > x() + width() - diff)) ||          //Right
           //Left-Top
           ((e_pos.y() < y() + diff) &&                     //Top
            (e_pos.x() < x() + diff)) ||                    //Left
           //Right-Top
           ((e_pos.y() < y() + diff) &&                     //Top
            (e_pos.x() > x() + width() - diff))             //Right
      )
   {
       //Left-Bottom
       if ((e_pos.y() > y() + height() - diff) &&           //Bottom
           (e_pos.x() < x() + diff)) {                      //Left
           mode = RESIZEBL;
           setCursor(QCursor(Qt::SizeBDiagCursor));
       }
       //Right-Bottom
       if ((e_pos.y() > y() + height() - diff) &&           //Bottom
           (e_pos.x() > x() + width() - diff)) {            //Right
           mode = RESIZEBR;
           setCursor(QCursor(Qt::SizeFDiagCursor));
       }
       //Left-Top
       if ((e_pos.y() < y() + diff) &&                      //Top
           (e_pos.x() < x() + diff)) {                      //Left
           mode = RESIZETL;
           setCursor(QCursor(Qt::SizeFDiagCursor));
       }
       //Right-Top
       if ((e_pos.y() < y() + diff) &&                      //Top
           (e_pos.x() > x() + width() - diff)) {            //Right
           mode = RESIZETR;
           setCursor(QCursor(Qt::SizeBDiagCursor));
       }
   }
   // проверка положения курсора по горизонтали
   else if ((e_pos.x() < x() + diff) ||             //Left
           ((e_pos.x() > x() + width() - diff))) {  //Right
       if (e_pos.x() < x() + diff) {                //Left
           setCursor(QCursor(Qt::SizeHorCursor));
           mode = RESIZEL;
       } else {                                     //Right
           setCursor(QCursor(Qt::SizeHorCursor));
           mode = RESIZER;
       }
   }
   // проверка положения курсора по вертикали
   else if (((e_pos.y() > y() + height() - diff)) || //Bottom
             (e_pos.y() < y() + diff)) {             //Top
       if (e_pos.y() < y() + diff) {                 //Top
           setCursor(QCursor(Qt::SizeVerCursor));
           mode = RESIZET;
       } else {                                      //Bottom
           setCursor(QCursor(Qt::SizeVerCursor));
           mode = RESIZEB;
       }
   } else {
       setCursor(QCursor(Qt::ArrowCursor));
       mode = MOVE;
   }

}

void TContainer::mouseReleaseEvent(QMouseEvent *e) {

   QWidget::mouseReleaseEvent(e);

}

void TContainer::mouseMoveEvent(QMouseEvent *e) {

   QWidget::mouseMoveEvent(e);
   if (!m_isEditing) return;
   if (!m_infocus) return;
   if (!e->buttons() & Qt::LeftButton) {
       QPoint p = QPoint(e->x()+geometry().x(), e->y()+geometry().y());
       setCursorShape(p);
       return;
   }

   if ((mode MOVE || mode NONE) && e->buttons() && Qt::LeftButton) {

       QPoint toMove = e->globalPos() - position;
       if (toMove.x() < 0) return;
       if (toMove.y() < 0) return;
       if (toMove.x() > this->parentWidget()->width()-this->width()) return;
       move(toMove);
       emit newGeometry(this->geometry());
       this->parentWidget()->repaint();
       return;
   }
   if ((mode != MOVE) && e->buttons() && Qt::LeftButton) {
       switch (mode){
           case RESIZETL: {  //Left-Top
               int newwidth = e->globalX() - position.x() - geometry().x();
               int newheight = e->globalY() - position.y() - geometry().y();
               QPoint toMove = e->globalPos() - position;
               resize(this->geometry().width()-newwidth,this->geometry().height()-newheight);
               move(toMove.x(),toMove.y());
               break;
           }
           case RESIZETR: {  //Right-Top
               int newheight = e->globalY() - position.y() - geometry().y();
               QPoint toMove = e->globalPos() - position;
               resize(e->x(),this->geometry().height()-newheight);
               move(this->x(),toMove.y());
               break;
           }
           case RESIZEBL: {  //Left-Bottom
               int newwidth = e->globalX() - position.x() - geometry().x();
               QPoint toMove = e->globalPos() - position;
               resize(this->geometry().width()-newwidth,e->y());
               move(toMove.x(),this->y());
               break;
           }
           case RESIZEB: {   //Bottom
               resize(width(),e->y()); break;}
           case RESIZEL:  {  //Left
               int newwidth = e->globalX() - position.x() - geometry().x();
               QPoint toMove = e->globalPos() - position;
               resize(this->geometry().width()-newwidth,height());
               move(toMove.x(),this->y());
               break;
           }
           case RESIZET:  {  //Top
               int newheight = e->globalY() - position.y() - geometry().y();
               QPoint toMove = e->globalPos() - position;
               resize(width(),this->geometry().height()-newheight);
               move(this->x(),toMove.y());
               break;
           }
           case RESIZER:  {  //Right
               resize(e->x(),height()); break;}
           case RESIZEBR: {  //Right-Bottom
               resize(e->x(),e->y()); break;}
       }
       this->parentWidget()->repaint();
   }
   emit newGeometry(this->geometry());
   //QWidget::mouseMoveEvent(e);

}