看到一个博客问答关于qt拖动及拖拽,好像写得不错,没有细看,是实现自定义控件可以实现鼠标拖动控件及拉拽的另一种方法,先摘抄下来,后面详细研究下,原文链接:https://bbs.csdn.net/topics/390848708
仅供学习,转载请联系原博主,如有侵权请及时联系删除
qtdesigner源码中有
拖动原理:
利用QDrag类实现。
在开始拖动的时:把需要拖动的控件图形设置给QDrag实例,控件图形通过QPixmap::grabWidget获取。
然后把控件隐藏,这个时候鼠标移动就会有控件跟着动的效果了。
在QDrag释放的时候得到释放的位置,然后把控件移动到这个位置并显示。
改变大小原理:
当控件被选中的时候,给工具外面套上一个特殊的widget,这个weidget其实就是绘制了8个小块。当鼠标移动和点击到不同的小块上进行相应的处理。在拖动的时候时刻计算偏移量,然后设置控件大小和位置。
基本原理就是这样的。
我只知道怎么拖动控件,
比如你托动标题,就能拖动窗体。
你可以重写标题控件的mouseMoveEvent事件
void YourTitleLabel::mouseMoveEvent(QMouseEvent *e)
{
if(e->buttons() == Qt::LeftButton && m_bMoving)
{
QWidget* parentWidget = this->parentWidget();
QPoint parentPoint = parentWidget->pos();
parentPoint.setX(parentPoint.x() + e->x() - m_pressedPoint.x());
parentPoint.setY(parentPoint.y() + e->y() - m_pressedPoint.y());
QDesktopWidget *desktop = QApplication::desktop();
QRect deskRect = desktop->availableGeometry();
// 目标位置不能在任务栏下面,不能在左边移出一半
if( (parentPoint.y() < (deskRect.bottom() - 20))
&& (parentPoint.x() > (deskRect.left() - parentWidget->width() / 2)))
parentWidget->move(parentPoint);
}
QLabel::mouseMoveEvent(e);
}
注意标题栏的父是主窗体,这样拖动标题栏主窗体才会动。可以依次类推到你想要的其它控件
#ifndef QSELECTWIDGET_H
#define QSELECTWIDGET_H
#include
#include
class WidgetHandle: public QWidget
{
Q_OBJECT
public:
enum Type
{
LeftTop,
Top,
RightTop,
Right,
RightBottom,
Bottom,
LeftBottom,
Left,
TypeCount
};
WidgetHandle(QWidget* parent,Type t);
void setWidget(QWidget *w);
void setCurrent(bool b);
protected:
protected:
void paintEvent(QPaintEvent *);
void mousePressEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
protected:
void updateCursor();
void trySetGeometry(QWidget *w, int x, int y, int width, int height);
void tryResize(QWidget *w, int width, int height);
signals:
void sizeChanged(int x,int y,int width,int height);
void mouse_button_release(const QRect& old,const QRect & now);
protected:
Type m_type;
QWidget * m_widget;
bool m_current;
QPoint m_origPressPos;
QRect m_geom, m_origGeom;
};
class WidgetSelection: public QObject
{
Q_OBJECT
public:
WidgetSelection(QWidget *parent);
void setWidget(QWidget *w);
QWidget *widget();
bool isUsed() const;
void hide();
void show();
void update();
void updateGeometry();
void setCurrent(bool b);
protected:
bool eventFilter(QObject *object, QEvent *event);
protected slots:
void changedsize(int x,int y,int width,int height);
void mouse_button_release(const QRect& old,const QRect & now);
signals:
void sizeChanged(QWidget* wid,const QRect& old,const QRect & now);
protected:
WidgetHandle *m_handles[WidgetHandle::TypeCount];
QWidget *m_widget;
QWidget *m_formWindow;
};
class Selection : public QObject
{
Q_OBJECT
public:
Selection(QWidget *formwindow);
~Selection();
void clear();
void clearSelectionPool();
void repaintSelection(QWidget *w);
void repaintSelection();
bool isWidgetSelected(QWidget *w) const;
QWidgetList selectedWidgets() const;
WidgetSelection *addWidget(QWidget *w);
QWidget* removeWidget(QWidget *w);
QWidget* current();
void raiseList(const QWidgetList& l);
void raiseWidget(QWidget *w);
void updateGeometry(QWidget *w);
void hide(QWidget *w);
void show(QWidget *w);
void setCurrent(QWidget *w);
signals:
void sizeChanged(QWidget* wid,const QRect& old,const QRect & now);
private:
typedef QList SelectionPool;
SelectionPool m_selectionPool;
typedef QHash SelectionHash;
SelectionHash m_usedSelections;
WidgetSelection * m_current;
QWidget* m_formwindow;
};
#endif // QSELECTWIDGET_H
#include "qselectwidget.h"
#include
#include
WidgetHandle::WidgetHandle(QWidget *parent, Type t):
QWidget(parent),
m_type(t),
m_current(false)
{
setAttribute(Qt::WA_NoChildEventsForParent);
setMouseTracking(false);
setAutoFillBackground(true);
setBackgroundRole(QPalette::Text);
setFixedSize(6, 6);
updateCursor();
}
void WidgetHandle::updateCursor()
{
switch (m_type)
{
case LeftTop:
setCursor(Qt::SizeFDiagCursor);
break;
case Top:
setCursor(Qt::SizeVerCursor);
break;
case RightTop:
setCursor(Qt::SizeBDiagCursor);
break;
case Right:
setCursor(Qt::SizeHorCursor);
break;
case RightBottom:
setCursor(Qt::SizeFDiagCursor);
break;
case Bottom:
setCursor(Qt::SizeVerCursor);
break;
case LeftBottom:
setCursor(Qt::SizeBDiagCursor);
break;
case Left:
setCursor(Qt::SizeHorCursor);
break;
default:
setCursor(Qt::ArrowCursor);
break;
}
}
void WidgetHandle::setCurrent(bool b)
{
m_current=b;
this->update();
}
void WidgetHandle::setWidget(QWidget *w)
{
m_widget = w;
}
void WidgetHandle::paintEvent(QPaintEvent *)
{
QPainter p(this);
p.setPen(m_current? Qt::blue : Qt::black);
p.setBrush(QBrush(QColor(m_current? Qt::darkBlue : Qt::black)));
p.drawRect(0, 0, width() - 1, height() - 1);
}
void WidgetHandle::mousePressEvent(QMouseEvent *e)
{
e->accept();
if (!(m_widget && e->button() == Qt::LeftButton))
return;
QWidget *container = m_widget->parentWidget();
m_origPressPos = container->mapFromGlobal(e->globalPos());
m_geom = m_origGeom = m_widget->geometry();
}
void WidgetHandle::mouseMoveEvent(QMouseEvent *e)
{
if (!(m_widget && e->buttons() & Qt::LeftButton))
return;
e->accept();
QWidget *container = m_widget->parentWidget();
const QPoint rp = container->mapFromGlobal(e->globalPos());
const QPoint d = rp - m_origPressPos;
const QRect pr = container->rect();
switch (m_type)
{
case LeftTop:
{
if (rp.x() > pr.width() - 2 * width() || rp.y() > pr.height() - 2 * height())
return;
int w = m_origGeom.width() - d.x();
m_geom.setWidth(w);
int h = m_origGeom.height() - d.y();
m_geom.setHeight(h);
const int dx = m_widget->width() - w;
const int dy = m_widget->height() - h;
trySetGeometry(m_widget, m_widget->x() + dx, m_widget->y() + dy, w, h);
}
break;
case Top:
{
if (rp.y() > pr.height() - 2 * height())
return;
int h = m_origGeom.height() - d.y();
m_geom.setHeight(h);
const int dy = m_widget->height() - h;
trySetGeometry(m_widget, m_widget->x(), m_widget->y() + dy, m_widget->width(), h);
}
break;
case RightTop:
{
if (rp.x() < 2 * width() || rp.y() > pr.height() - 2 * height())
return;
int h = m_origGeom.height() - d.y();
m_geom.setHeight(h);
const int dy = m_widget->height() - h;
int w = m_origGeom.width() + d.x();
m_geom.setWidth(w);
trySetGeometry(m_widget, m_widget->x(), m_widget->y() + dy, w, h);
}
break;
case Right:
{
if (rp.x() < 2 * width())
return;
int w = m_origGeom.width() + d.x();
m_geom.setWidth(w);
tryResize(m_widget, w, m_widget->height());
}
break;
case RightBottom:
{
if (rp.x() < 2 * width() || rp.y() < 2 * height())
return;
int w = m_origGeom.width() + d.x();
m_geom.setWidth(w);
int h = m_origGeom.height() + d.y();
m_geom.setHeight(h);
tryResize(m_widget, w, h);
}
break;
case Bottom:
{
if (rp.y() < 2 * height())
return;
int h = m_origGeom.height() + d.y();
m_geom.setHeight(h);
tryResize(m_widget, m_widget->width(), h);
}
break;
case LeftBottom:
{
if (rp.x() > pr.width() - 2 * width() || rp.y() < 2 * height())
return;
int w = m_origGeom.width() - d.x();
m_geom.setWidth(w);
int h = m_origGeom.height() + d.y();
m_geom.setHeight(h);
int dx = m_widget->width() - w;
trySetGeometry(m_widget, m_widget->x() + dx, m_widget->y(), w, h);
}
break;
case Left:
{
if (rp.x() > pr.width() - 2 * width())
return;
int w = m_origGeom.width() - d.x();
m_geom.setWidth(w);
const int dx = m_widget->width() - w;
trySetGeometry(m_widget, m_widget->x() + dx, m_widget->y(), w, m_widget->height());
}
break;
default: break;
}
}
void WidgetHandle::mouseReleaseEvent(QMouseEvent *e)
{
if (e->button() != Qt::LeftButton)
return;
e->accept();
emit mouse_button_release(m_origGeom,m_geom);
}
void WidgetHandle::trySetGeometry(QWidget *w, int x, int y, int width, int height)
{
int minw = w->minimumSize().width();
minw = qMax(minw, 20);
int minh = w->minimumSize().height();
minh = qMax(minh, 20);
if (qMax(minw, width) > w->maximumWidth() ||
qMax(minh, height) > w->maximumHeight())
return;
if (width < minw && x != w->x())
x -= minw - width;
if (height < minh && y != w->y())
y -= minh - height;
emit sizeChanged(x, y, qMax(minw, width), qMax(minh, height));
}
void WidgetHandle::tryResize(QWidget *w, int width, int height)
{
int minw = w->minimumSize().width();
minw = qMax(minw, 16);
int minh = w->minimumSize().height();
minh = qMax(minh, 16);
emit sizeChanged(w->x(),w->y(),qMax(minw, width), qMax(minh, height));
}
WidgetSelection::WidgetSelection(QWidget *parent) :
m_widget(0),
m_formWindow(parent)
{
for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i)
{
m_handles[i] = new WidgetHandle(m_formWindow, static_cast(i));
connect(m_handles[i],SIGNAL(sizeChanged(int,int,int,int)),this,SLOT(changedsize(int,int,int,int)));
connect(m_handles[i],SIGNAL(mouse_button_release(QRect,QRect)),this,SLOT(mouse_button_release(QRect,QRect)));
}
hide();
}
void WidgetSelection::setCurrent(bool b)
{
for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i)
{
m_handles[i]->setCurrent(b);
}
}
void WidgetSelection::setWidget(QWidget *w)
{
if (m_widget != 0)
{
QWidget* wid=m_widget;
while(wid!=NULL)
{
wid->removeEventFilter(this);
wid=wid->parentWidget();
if(wid==m_formWindow)
{
break;
}
}
}
if (w == 0) {
hide();
m_widget = 0;
return;
}
m_widget = w;
for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i)
{
m_handles[i]->setWidget(m_widget);
}
QWidget* wid=m_widget;
while(wid!=NULL)
{
wid->installEventFilter(this);
wid=wid->parentWidget();
if(wid==m_formWindow)
{
break;
}
}
updateGeometry();
show();
}
bool WidgetSelection::isUsed() const
{
return m_widget != 0;
}
QWidget *WidgetSelection::widget()
{
return m_widget;
}
void WidgetSelection::updateGeometry()
{
if (!m_widget || !m_widget->parentWidget())
return;
QPoint p = m_widget->mapToGlobal(QPoint(0,0));
p = m_formWindow->mapFromGlobal(p);
const QRect r(p, m_widget->size());
const int w = 6;
const int h = 6;
for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i)
{
WidgetHandle *hndl = m_handles[ i ];
if (!hndl)
continue;
switch (i)
{
case WidgetHandle::LeftTop:
hndl->move(r.x() - w / 2, r.y() - h / 2);
break;
case WidgetHandle::Top:
hndl->move(r.x() + r.width() / 2 - w / 2, r.y() - h / 2);
break;
case WidgetHandle::RightTop:
hndl->move(r.x() + r.width() - w / 2, r.y() - h / 2);
break;
case WidgetHandle::Right:
hndl->move(r.x() + r.width() - w / 2, r.y() + r.height() / 2 - h / 2);
break;
case WidgetHandle::RightBottom:
hndl->move(r.x() + r.width() - w / 2, r.y() + r.height() - h / 2);
break;
case WidgetHandle::Bottom:
hndl->move(r.x() + r.width() / 2 - w / 2, r.y() + r.height() - h / 2);
break;
case WidgetHandle::LeftBottom:
hndl->move(r.x() - w / 2, r.y() + r.height() - h / 2);
break;
case WidgetHandle::Left:
hndl->move(r.x() - w / 2, r.y() + r.height() / 2 - h / 2);
break;
default:
break;
}
}
}
void WidgetSelection::hide()
{
for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i)
{
WidgetHandle *h = m_handles[ i ];
if (h)
h->hide();
}
}
void WidgetSelection::show()
{
for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i)
{
WidgetHandle *h = m_handles[ i ];
if (h) {
h->show();
h->raise();
}
}
}
void WidgetSelection::update()
{
for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i)
{
WidgetHandle *h = m_handles[ i ];
if (h)
h->update();
}
}
bool WidgetSelection::eventFilter(QObject *object, QEvent *event)
{
QObject *o=m_widget;
while(1)
{
if(o==object)
{
break;
}
o=o->parent();
if(o==NULL)
{
return false;
}
}
switch (event->type()) {
default: break;
case QEvent::Move:
case QEvent::Resize:
case QEvent::ParentChange:
updateGeometry();
break;
case QEvent::ZOrderChange:
show();
break;
}
return false;
}
void WidgetSelection::changedsize(int x, int y, int width, int height)
{
m_widget->setProperty("geometry",QRect(x,y,width,height));
updateGeometry();
}
void WidgetSelection::mouse_button_release(const QRect &old, const QRect &now)
{
emit sizeChanged(m_widget,old,now);
}
Selection::Selection(QWidget *formwindow):
m_current(NULL),
m_formwindow(formwindow)
{
}
Selection::~Selection()
{
clearSelectionPool();
}
void Selection::clear()
{
if (!m_usedSelections.empty())
{
const SelectionHash::iterator mend = m_usedSelections.end();
for (SelectionHash::iterator it = m_usedSelections.begin(); it != mend; ++it)
{
it.value()->setWidget(0);
}
m_usedSelections.clear();
}
}
void Selection::clearSelectionPool()
{
clear();
qDeleteAll(m_selectionPool);
m_selectionPool.clear();
}
WidgetSelection *Selection::addWidget(QWidget *w)
{
WidgetSelection *rc= m_usedSelections.value(w);
if (rc != 0)
{
rc->show();
return rc;
}
const SelectionPool::iterator pend = m_selectionPool.end();
for (SelectionPool::iterator it = m_selectionPool.begin(); it != pend; ++it)
{
if (! (*it)->isUsed()) {
rc = *it;
break;
}
}
if (rc == 0) {
rc = new WidgetSelection(m_formwindow);
connect(rc,SIGNAL(sizeChanged(QWidget*,QRect,QRect)),this,SIGNAL(sizeChanged(QWidget*,QRect,QRect)));
m_selectionPool.push_back(rc);
}
m_usedSelections.insert(w, rc);
rc->setWidget(w);
return rc;
}
QWidget* Selection::removeWidget(QWidget *w)
{
WidgetSelection *s = m_usedSelections.value(w);
if (!s)
return w;
if(m_current==s)
{
m_current->setCurrent(false);
m_current=NULL;
}
s->setWidget(0);
m_usedSelections.remove(w);
if (m_usedSelections.isEmpty())
return 0;
return (*m_usedSelections.begin())->widget();
}
void Selection::repaintSelection(QWidget *w)
{
if (WidgetSelection *s = m_usedSelections.value(w))
s->update();
}
void Selection::repaintSelection()
{
const SelectionHash::iterator mend = m_usedSelections.end();
for (SelectionHash::iterator it = m_usedSelections.begin(); it != mend; ++it) {
it.value()->update();
}
}
bool Selection::isWidgetSelected(QWidget *w) const{
return m_usedSelections.contains(w);
}
QWidgetList Selection::selectedWidgets() const
{
return m_usedSelections.keys();
}
void Selection::raiseList(const QWidgetList& l)
{
const SelectionHash::iterator mend = m_usedSelections.end();
for (SelectionHash::iterator it = m_usedSelections.begin(); it != mend; ++it) {
WidgetSelection *w = it.value();
if (l.contains(w->widget()))
w->show();
}
}
void Selection::raiseWidget(QWidget *w)
{
if (WidgetSelection *s = m_usedSelections.value(w))
s->show();
}
void Selection::updateGeometry(QWidget *w)
{
if (WidgetSelection *s = m_usedSelections.value(w))
{
s->updateGeometry();
}
}
void Selection::hide(QWidget *w)
{
if (WidgetSelection *s = m_usedSelections.value(w))
s->hide();
}
void Selection::show(QWidget *w)
{
if (WidgetSelection *s = m_usedSelections.value(w))
s->show();
}
void Selection::setCurrent(QWidget *w)
{
WidgetSelection *s = m_usedSelections.value(w);
if(m_current==s)
{
return;
}
if(m_current!=NULL)
{
m_current->setCurrent(false);
}
m_current=s;
if(m_current!=NULL)
{
m_current->setCurrent(true);
}
}
QWidget* Selection::current()
{
return m_current==NULL?NULL:m_current->widget();
}
这个就是我(回答问题的人)做的一个控件拖拽大小的源码。
把需要改变大小的widget指针添加到Selection实例中就可以了。
把需要改变大小的widget指针添加到Selection实例中就可以了。
这儿好像说法不对 先实例一个 Selection出来 然后再调用 AddWidget(QWidget *w) 的方法 刚你要缩放的控件的指针传进去就可以了 可用