| 
 Название: Виджет-контейнер: перемещаемый и изменяемый размер
 Отправлено: aliks-os от Мая 20, 2012,  16:08
 
 Я хочу представить виджет который можно перемещать и у которого можно изменять размеры. Данный виджет может служить контейнером для других виджетов, таких как QLabel, QTableWidget и так далее. Данный виджет используется мною уже в нескольких проектах. Надеюсь он будем вам полезен mainwindow.h /*Programmer Aleksey Osipov
 email: aliks-os@yandex.ru
 */
 
 #ifndef MAINWINDOW_H
 #define MAINWINDOW_H
 
 #include <QMainWindow>
 #include "tcontainer.h"
 
 namespace Ui {
 class MainWindow;
 }
 
 class MainWindow : public QMainWindow
 {
 Q_OBJECT
 
 public:
 explicit MainWindow(QWidget *parent = 0);
 ~MainWindow();
 
 private:
 Ui::MainWindow *ui;
 };
 
 #endif // MAINWINDOW_H
 
mainwindow.cpp /*Programmer Aleksey Osipov
 email: aliks-os@yandex.ru
 */
 #include "mainwindow.h"
 #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
 */
 #ifndef TCONTAINER_H
 #define TCONTAINER_H
 
 #include <QWidget>
 #include <QMouseEvent>
 #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:
 
 };
 
 #endif // TCONTAINER_H
tcontainer.cpp @/*
 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 &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 && 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);
 }
 
 Название: Re: Виджет-контейнер: перемещаемый и изменяемый размер
 Отправлено: iroln от Мая 20, 2012,  16:45
 
 Лучше бы было если бы проект в архиве выложил. А ещё скриншот, а то я не понял, что с ним делать. :) 
 Название: Re: Виджет-контейнер: перемещаемый и изменяемый размер
 Отправлено: aliks-os от Мая 20, 2012,  16:49
 
 Лучше бы было если бы проект в архиве выложил. А ещё скриншот, а то я не понял, что с ним делать. :)
 Что с ним делать написано вверху
 Название: Re: Виджет-контейнер: перемещаемый и изменяемый размер
 Отправлено: Hrundel от Октября 19, 2012,  22:25
 
 Я просто скопировал текст и раскидал в соответствующие файлы.Запустил на компиляцию и получил 12 ошибок, все одно содержания:
 
 undefined reference to `vtable for TContainer'
 
 Будьте добры объясните почему.
 Спасибо.
 
 
 |