Reputation: 207
I added a QWidget in a Parent QWidget like the picture below:
Inside Child QWidget i programmed using mouse to move it inside Parent QWidget.
void ExportComponent::mousePressEvent(QMouseEvent *event)
{
offset = event->pos();
}
void ExportComponent::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton)
{
this->move(mapToParent(event->pos() - offset));
}
}
It performs well but the thing is it can also move out the Parent QWidget size. Like this:
How can i make the Child QWidget can only move within the ParentQWidget?
Upvotes: 2
Views: 1082
Reputation: 207
I combined @Bowdzone's code with mine to give a better solution. This new algorithm works much smoother and still satisfy my purpose.
void ExportComponent::mouseMoveEvent(QMouseEvent *event)
{
//Using left mouse to move the control
if (event->buttons() & Qt::LeftButton)
{
//Excute movement follow mouse position
move(mapToParent(event->pos() - m_offset));
//Make sure control do not move out parent size
if (x() < 0)
move(1, y());
if (y() < 0)
move(x(), 1);
if (x() + width() > parentWidget()->width())
move(parentWidget()->width() - 1 - width(), y());
if (y() + height() > parentWidget()->height())
move(x(), parentWidget()->height() - 1 - height());
}
}
Upvotes: 1
Reputation: 3854
You can add an additonal if
clause in the mouseMoveEvent
to check whether the child widget is still within the parents' boundaries. The following example does that:
void ExportComponent::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton)
{
QPoint newpos_min = mapToParent(event->pos()-offset);
QPoint newpos_max = QPoint(newpos_min.x() + this->width(), newpos_min.y() + this->height());
if(newpos_min.x() > 0 &&
newpos_min.y() > 0 &&
newpos_max.x() < this->parentWidget()->width() &&
newpos_max.y() < this->parentWidget()->height()){
this->move(mapToParent(event->pos() - offset));
}
}
}
However, you now have the problem, that if either the new x
or y
position is out of bounds, no movement is possible anymore. There are several ways to deal with that.
One way would be to dynamically update the offset in the mouseMoveEvent
. A really simple version is updating the offset if the movement does not work:
...
this->move(mapToParent(event->pos() - offset));
}else{
offset = event->pos();
}
...
Still not too nice as this creates a large gap between the cursor and the widget if the mouse moves back into the allowed area.
Another possibilty is to seperate the x and the y movement and check dem individually:
if(newpos_min.y() > 0 &&
newpos_max.y() < this->parentWidget()->height()){
this->move(this->x(), mapToParent(event->pos() - offset).y());
}
if(newpos_min.x() > 0 &&
newpos_max.x() < this->parentWidget()->width()){
this->move(mapToParent(event->pos() - offset).x(), this->y());
}
which is a better version in my opinion.
Still, updating the offset might add some improvements. You just need to make sure, that the curso is back on the widget before moving it again.
Upvotes: 3