欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

QT实现拖动没有标题栏的窗口

程序员文章站 2022-07-13 23:02:27
...

本文说明如何拖动没有标题栏的窗口,分别处理是否带有子窗口的情况。其中第一部分引用的是其他人的代码。

当没有子窗口时

本节内容引用自:QtWidget: 鼠标拖动窗口(没有标题栏时)



void ShapedClock::mousePressEvent(QMouseEvent *event) {
    if (event->button() == Qt::LeftButton) {
        dragPosition = event->globalPos() - frameGeometry().topLeft();
        event->accept();
    }
}
void ShapedClock::mouseMoveEvent(QMouseEvent *event) {
    if (event->buttons() & Qt::LeftButton) {
        move(event->globalPos() - dragPosition);
        event->accept();
    }
}

const QPoint & QMouseEvent::globalPos () const

Returns the global position of the mouse cursor at the time of the event. This is important on asynchronous window systems like X11. Whenever you move your widgets around in response to mouse events, globalPos() may differ a lot from the current pointer position QCursor::pos(), and from QWidget::mapToGlobal(pos()).

 

QPoint QWidget::mapToGlobal ( const QPoint & pos ) const

Translates the widget coordinate pos to global screen coordinates. For example, mapToGlobal(QPoint(0,0)) would give the global coordinates of the top-left pixel of the widget.

 

QPoint QWidget::mapFromGlobal ( const QPoint & pos ) const

Translates the global screen coordinate pos to widget coordinates.


===============================================华丽的分割线===============================================

当有子窗口时

以上只能用于没有子窗口的Widget,如果有父窗口就会发生父窗口不动,子窗口移动的尴尬情况。

以下代码用于让父窗口移动,FormMainCenter是子窗口,它的父窗口为MainForm:

头文件:

class FormMainCenter : public QWidget
{
    Q_OBJECT

public:
    explicit FormMainCenter(QWidget *parent = 0);
    ~FormMainCenter();

    virtual void mousePressEvent(QMouseEvent *event);
    virtual void mouseMoveEvent(QMouseEvent *event);
private:
    Ui::FormMainCenter *ui;
    //记录窗口拖动的位置
    QPoint dragPosition;
    QPoint orignalPositon;
};

CPP文件


void FormMainCenter::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        //计算点击的相对位置,确定鼠标是否点这个位置是否可以拖动(这里设定窗口上点击可拖动的范围为700*120)。
        QPoint pt = mapFromGlobal(event->globalPos());
        if(!(pt.x() < 700 && pt.y() < 120))
        {
            //qDebug() << tr("click ") << pt.x() << "," << pt.y();
            orignalPositon.setX(-1);
            orignalPositon.setY(-1);
            event->accept();
            return;
        }
        //使用dragPosition保存开始移动前鼠标点击的位置,用于计算拖动范围。
        dragPosition = event->globalPos();
        //使用orignalPositon保存开始移动前的主窗口位置
        orignalPositon = parentWidget()->pos();
        //qDebug() << tr("click ") << dragPosition.x() << "," << dragPosition.y();
        //qDebug() << tr("parent pos") << parentWidget()->pos().x() << "," << parentWidget()->pos().y();
        event->accept();
    }
}
void FormMainCenter::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton)
    {
        //qDebug() << tr("mouse move pos:") << event->globalPos();
        //qDebug() << tr("parent pos:") << parentWidget()->pos();
        //qDebug() << tr("delta:") << (event->globalPos() - dragPosition);
        // 当前鼠标的位置减去开始时保存的位置,就是拖动过程中的偏移量
        // 将这个偏移量加上拖动前的父窗口位置,就是父窗口新的位置
        if(!(orignalPositon.x() == -1 && orignalPositon.y() == -1))
            parentWidget()->move(orignalPositon + (event->globalPos() - dragPosition));
        event->accept();
    }
}


移动一个窗口时同时移动另外一个窗口

保持相对位置不变
//dragPosition 用于存放开始拖动时鼠标相对于本窗口的相对位置。
static QPoint dragPosition = {0,0};
void DlgAdvanceSetting::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        QPoint pt = mapFromGlobal(event->globalPos());
        if(pt.y() < 50)
        {
            //qDebug() << "(mousePressEvent)Fram geometry topleft(" << frameGeometry().topLeft().x() << "," << frameGeometry().topLeft().y() << ")";
            dragPosition = event->globalPos() - frameGeometry().topLeft();
            event->accept();
        }
    }
}

void DlgAdvanceSetting::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton)
    {
        QPoint pt = mapFromGlobal(event->globalPos());
        if(pt.y() < 50)
        {
            QPoint RelativePos = {165,0};
            if(dlgMenuSetting)
            {
                //获取菜单设置窗口相对于本窗口的偏移,移动前后需要保证不变。
                RelativePos = dlgMenuSetting->frameGeometry().topLeft() - frameGeometry().topLeft();
                //qDebug() << "calc r = (" << RelativePos.x() << "," << RelativePos.y() << ");";
            }
            //移动自己
            //qDebug() << "(mouseMoveEvent)Fram geometry topleft(" << frameGeometry().topLeft().x() << "," << frameGeometry().topLeft().y() << ")";
            move(event->globalPos() - dragPosition);
            if(dlgMenuSetting)
            {
                //移动菜单设置对话框,由于它逻辑上是高级设置的子窗口。
                //由于事实上不是,那么在算出相对位置后,需要使用此窗口对应系统桌面的坐标调用它的move成员。
                //qDebug() << "move r = (" << RelativePos.x() << "," << RelativePos.y() << ");";
                QPoint globalPos = this->pos();
                globalPos.setX(globalPos.x() + RelativePos.x());
                globalPos.setY(globalPos.y() + RelativePos.y());
                dlgMenuSetting->move(globalPos);
            }
            event->accept();
        }
    }
}