Название: Виджет-контейнер: перемещаемый и изменяемый размер
Отправлено: 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'
Будьте добры объясните почему. Спасибо.
|