演示及其理论
演示:
理论:首先获取父窗口下所有子窗口,然后拖动控件去检测,检测成功后使用画家类绘制辅助线。
1、拖动控件
拖动控件需要满足以下条件:鼠标点击处有控件,鼠标位置的偏移。
/
void MyPushButton::mousePressEvent(QMouseEvent *e)
{
if(e->button()==Qt::LeftButton){
QPoint mousePos = e->pos();
IsMousePress=true;
QWidget * scele = childAt(mousePos);//获取鼠标点击位置的控件
lastMousePos=e->globalPos();//获取全局位置
}
QWidget::mousePressEvent(e);
}
void MyPushButton::mouseReleaseEvent(QMouseEvent *e)
{
if(e->button()==Qt::LeftButton){
IsMousePress=false;
}
QWidget::mouseReleaseEvent(e);
}
void MyPushButton::mouseMoveEvent(QMouseEvent *e)
{
if(IsMousePress&&你的控件!=null){
QPoint delta=e->globalPos()-lastMousePos;//鼠标位置差值,没有这个会让控件原点为鼠标坐标
你的控件->move(pos()+delta);//移动代码
lastMousePos=e->globalPos();//重置
}
QWidget::mouseMoveEvent(e);//消息传递
}
很简单的移动。
2、控件对齐
首先获取控件父对象的所有子控件,很绕吧,因为有的时候我不知道这个控件的父对象是谁时用的上。
QList<QWidget *> childWidgets;//全局变量
childWidgets=findChildren<QWidget *>();//这个是在知晓其父对象时可以使用
childWidgets= 你的控件->parentWidget()->findChildren<QWidget *>();//不知道父窗口的情况
随后,需要一个判定条件,当鼠标拖着控件靠近另一个控件时控件就会吸附上去,但是很难分开。这个时候就需要一个判定条件,在鼠标点击事件中获取鼠标相对于控件的距离。
//全局变量
int last_mouse_pos_x;
int last_mouse_pos_y;
//鼠标按下事件中记录当前鼠标的位置相对与控件的距离
last_mouse_pos_x=e->x()-scele_widget->geometry().left();
last_mouse_pos_y=e->y()-scele_widget->geometry().top();
现在所需的所有变量都有了,就可以开始了!
void Desginer::mouseMoveEvent(QMouseEvent *e)
{
if (e->buttons() & Qt::LeftButton) {;
// 如果有拖动的控件
if (scele_widget) {
//qDebug()<<last_mouse_pos;
foreach(QWidget * sele,childWidgets){
if(sele!=scele_widget){//排除与自己检测
int x_distance = scele_widget->geometry().left() - sele->geometry().left();//与另一个控件的距离检测
int y_distance=scele_widget->geometry().top()-sele->geometry().top();
int c_distance=scele_widget->geometry().center().x()-sele->geometry().center().x();
if(qAbs(x_distance)<10 &&qAbs(qAbs(e->x()-scele_widget->geometry().left())-last_mouse_pos_x)<=10 ){//当距离小于10,鼠标当前与控件的相对距离减去按下时的距离小于时才会执行对齐
isleft=true;//用于绘制辅助线
scele_widget->move(sele->x(),scele_widget->y());//x轴对齐
}
else if (qAbs(x_distance)>10){
isleft=false;
}
if(qAbs(y_distance)<10&&qAbs(qAbs(e->y()-scele_widget->geometry().top())-last_mouse_pos_y)<=10){
istop=true;
scele_widget->move(scele_widget->x(),sele->y());//y轴对齐
}
else if(qAbs(y_distance)>10){
istop=false;
}
if(qAbs(c_distance)<10&&qAbs(qAbs(e->x()-scele_widget->geometry().left())-last_mouse_pos_x)<=10){
iscenter=true;
scele_widget->move(sele->geometry().center().x()-scele_widget->width()/2,scele_widget->y());//中心对齐
}
else{
iscenter=false;
}
}
if(qAbs(qAbs(e->x()-scele_widget->geometry().left())-last_mouse_pos_x)>15){
//这里是在鼠标相对位置改变后重置其相对位置以便于下次检测
last_mouse_pos_x=e->x()-scele_widget->geometry().left();
}
else if(qAbs(qAbs(e->y()-scele_widget->geometry().top())-last_mouse_pos_y)>15){
last_mouse_pos_y=e->y()-scele_widget->geometry().top();
}
}
}
}
QWidget::mouseMoveEvent(e);//这句是将事件传递给上层,没有这个的的话顶层窗口接收不到
}
3、画辅助线
void Desginer::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QSize widgetsize=this->size();
painter.drawRect(0,0,widgetsize.width()-1,widgetsize.height()-1);
QPen pen;
pen.setStyle(Qt::DashLine);
painter.setPen(pen);
if(isleft&&scele_widget!=NULL){
painter.drawLine(scele_widget->x()-1,0,scele_widget->x()-1,this->height());
update();//刷新
//qDebug()<<"x轴对齐"<<isleft;
}
else{
update();
}
if(istop&&scele_widget!=NULL){
painter.drawLine(0,scele_widget->y()-1,this->width(),scele_widget->y()-1);
update();
//qDebug()<<"y轴对齐"<<istop;
}
else{
update();
}
if(iscenter&&scele_widget!=NULL){
painter.drawLine(scele_widget->geometry().center().x(),0,scele_widget->geometry().center().x(),this->width());
update();
}
else{
update();
}
}