如何通过鼠标拖放来更改布局中窗口小部件的顺序?

时间:2016-03-20 18:32:55

标签: qt layout widget

我从QWidget创建了自己的课程,重新定义了paintEvent()mousePressEvent()mouseReleaseEvent()mouseMoveEvent()。所有用于移动小部件的方法都超过其他小部件(黄色)。

当我在布局中创建我的小部件时,它看起来像这样:

但是,当我将黑色小部件移动到底部并将红色移动到顶部时,这样:

并调整窗口大小,所有小部件都刷新到对齐位置:

但我想,当我将一个小部件移动到另一个小部件时,小部件应该在新的位置对齐布局,如下所示:

我应该重新定义哪个功能呢?

P.S。 There is一段代码,可以在布局中移动小部件位置(更改其索引),但我不知道如何找出他们的(x,y)位置来计算布局中的新索引。我想,我可以在resizeEvent()中完成。 但是当事件发出时,位置已经变为旧的。 (比如在移动1张照片之前),我需要移动后的位置(比如在secon图片上)。如何在对齐之前获取小部件的位置? 或者如何通过拖放鼠标来改变布局中窗口小部件的顺序?

1 个答案:

答案 0 :(得分:0)

我编写自己的小部件,然后重新定义以下方法:mouseReleaseEvent(), paintEvent(), mousePressEvent(), mouseMoveEvent()。在mousePressEvent()中,我在图中保持旧的X和Y位置以及鼠标位置。然后在mouseMoveEvent()中,我计算是否最小化鼠标移动距离并将窗口小部件移动到新位置(它不会在布局中移动窗口小部件索引)。在它之后,如果发出mouseReleaseEvent(),我只计算移动小部件的新索引并更改和更新父布局。如果窗口小部件的移动小于高度,则布局只会更新而不更改窗口小部件索引。

void SimpleWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (!(event->buttons() & Qt::LeftButton))
        return;
    if (!IsMinimumDistanceRiched(event))
    {
        return;
    }
    int y = event->globalY() - mouseClickY + oldY;
    int BottomBorder = parentWidget->geometry().height() - this->geometry().height();
    if(y < 0) y = 0;
    else if(y > BottomBorder) y = BottomBorder;
    move(oldX, y);
}

void SimpleWidget::mousePressEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton)
        dragStartPosition = event->pos();
    oldX = this->geometry().x();
    oldY = this->geometry().y();
    mouseClickX = event->globalX();
    mouseClickY = event->globalY();
}

bool SimpleWidget::IsMinimumDistanceRiched(QMouseEvent *event)
{
    return (event->pos() - dragStartPosition).manhattanLength() >= QApplication::startDragDistance();
}

bool SimpleWidget::moveInLayout(QWidget *widget, MoveDirection direction)
{
    QVBoxLayout* myLayout = qobject_cast<QVBoxLayout*>(widget->parentWidget()->layout());

    const int index = myLayout->indexOf(widget);
    if (direction == MoveUp && index == 0)
    {
        return false;
    }
    if (direction == MoveDown && index == myLayout->count()-1 )
    {
        return false;
    }
    const int newIndex = direction == MoveUp ? index - 1 : index + 1;
    myLayout->removeWidget(widget);
    myLayout->insertWidget(newIndex , widget);
    return true;
}

void SimpleWidget::paintEvent(QPaintEvent *)
{
    QStyleOption o;
    o.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &o, &p, this);
}

void SimpleWidget::mouseReleaseEvent(QMouseEvent *)
{
    int y = geometry().y();
    MoveDirection direct;
    int offset;
    if(oldY > y)
    {
        offset = oldY - y;
        direct = MoveUp;
    }
    else if(oldY < y)
    {
        offset = y - oldY;
        direct = MoveDown;
    }
    int count = offset/height();
    for(int i = 0; i < count; i++)
    {
        moveInLayout(this, direct);
    }
    update();
    QVBoxLayout* myLayout = qobject_cast<QVBoxLayout*>(this->parentWidget->layout());
    myLayout->update();
    this->saveGeometry();
}