Cesar
Cesar

Reputation: 399

Restoring FramelessWindow position after maximized

I'm writing some functions to move, maximize, and restore a frameless window built using Qt.

When the window gets maximized by double clicking on it, and the user tries to drag it, I'm not figuring out how to properly return it to her previous position.

Example:

class MainWindow: public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow() {};

    QWidget *titlebar_widget;

    bool mMoving;
    bool maximized;

    QPoint mLastMousePosition;
    QPoint mLastMousePositionBeforeMaximize;

    void mousePressEvent(QMouseEvent* event) 
    {
        if (!titlebar_widget->underMouse())
            return;

        if (event->button() == Qt::LeftButton) 
        {
            mMoving = true;
            mLastMousePosition = event->pos();
        }
    }

    void mouseMoveEvent(QMouseEvent* event)
    {
        if (!titlebar_widget->underMouse())
            return;

        if ((maximized) && (event->buttons().testFlag(Qt::LeftButton) && mMoving))
        {
            slot_restored();
            maximized = false;
            mLastMousePosition = mLastMousePositionBeforeMaximize;
            return;
        }

        if (event->buttons().testFlag(Qt::LeftButton) && mMoving)
            this->move(this->pos() + (event->pos() - mLastMousePosition));
    }

    void mouseReleaseEvent(QMouseEvent* event) 
    {
        if (!titlebar_widget->underMouse())
            return;

        if (event->button() == Qt::LeftButton)
            mMoving = false;
    }

    void mouseDoubleClickEvent(QMouseEvent* event)
    {
        Q_UNUSED(event);

        if (!titlebar_widget->underMouse())
            return;

        if (event->button() != Qt::LeftButton)
            return;

        maximized = !maximized;
        if (maximized)
        {
            mLastMousePositionBeforeMaximize = event->pos();
            slot_maximized();
        }
        else
            slot_restored();
    }

    void slot_minimized() { setWindowState(Qt::WindowMinimized); }
    void slot_restored() { setWindowState(Qt::WindowNoState); }
    void slot_maximized() { setWindowState(Qt::WindowMaximized); }

private:
    Ui::MainWindowClass ui;
};

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);

    ui.centralWidget->setStyleSheet("background-color: rgba(255, 255, 255, 155);");
    
    titlebar_widget = ui.centralWidget;
    setAttribute(Qt::WA_TranslucentBackground);
    setWindowFlags(Qt::FramelessWindowHint);
}

To be more precise my question lies here:

        // The window is maximized, user has leftbutton down, and is 
        // trying to move it.
        if ((maximized) && (event->buttons().testFlag(Qt::LeftButton) && mMoving))
        {
            slot_restored();
            maximized = false;
            mLastMousePosition = mLastMousePositionBeforeMaximize;
        }

Then the window is restored to her previous pos/size slot_restored(); and the following code moves the window around:

        if (event->buttons().testFlag(Qt::LeftButton) && mMoving)
            this->move(this->pos() + (event->pos() - mLastMousePosition));

But at this point I'm getting a weird movement, its moving the window to a different position than it was before:

enter image description here

In the gif isn't much noticeable because of the fps, but the window is jumping around.

How to properly calculate her position when it gets restored by dragging?

Upvotes: 3

Views: 150

Answers (2)

Parisa.H.R
Parisa.H.R

Reputation: 3893

why do you define UI object like this Ui::MainWindowClass ui;?

The only thing that I changed in your code was this and it works well for me I create the default widget mainWindow and this is:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMouseEvent>

QT_BEGIN_NAMESPACE
namespace Ui
{
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow: public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);

    ~MainWindow();


    QWidget *titlebar_widget;
    bool     mMoving;
    bool     maximized;
    QPoint   mLastMousePosition;
    QPoint   mLastMousePositionBeforeMaximize;

    void  mousePressEvent(QMouseEvent *event)
    {
        if (!titlebar_widget->underMouse())
        {
            return;
        }

        if (event->button() == Qt::LeftButton)
        {
            mMoving            = true;
            mLastMousePosition = event->pos();
        }
    }

    void  mouseMoveEvent(QMouseEvent *event);

    void  mouseReleaseEvent(QMouseEvent *event);

    void  mouseDoubleClickEvent(QMouseEvent *event);

    void  slot_minimized();

    void  slot_restored();

    void  slot_maximized();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent):
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->centralwidget->setStyleSheet("background-color: rgba(255, 0, 0, 155);");

    titlebar_widget = ui->centralwidget;
    setAttribute(Qt::WA_TranslucentBackground);
    setWindowFlags(Qt::FramelessWindowHint);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void  MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    if (!titlebar_widget->underMouse())
    {
        return;
    }

    if ((maximized) && (event->buttons().testFlag(Qt::LeftButton) && mMoving))
    {
        slot_restored();
        maximized          = false;
        mLastMousePosition = mLastMousePositionBeforeMaximize;

        return;
    }

    if (event->buttons().testFlag(Qt::LeftButton) && mMoving)
    {
        this->move(this->pos() + (event->pos() - mLastMousePosition));
    }
}

void  MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    if (!titlebar_widget->underMouse())
    {
        return;
    }

    if (event->button() == Qt::LeftButton)
    {
        mMoving = false;
    }
}

void  MainWindow::mouseDoubleClickEvent(QMouseEvent *event)
{
    Q_UNUSED(event);

    if (!titlebar_widget->underMouse())
    {
        return;
    }

    if (event->button() != Qt::LeftButton)
    {
        return;
    }

    maximized = !maximized;

    if (maximized)
    {
        mLastMousePositionBeforeMaximize = event->pos();
        slot_maximized();
    }
    else
    {
        slot_restored();
    }
}

void  MainWindow::slot_minimized()
{
    setWindowState(Qt::WindowMinimized);
}

void  MainWindow::slot_restored()
{
    setWindowState(Qt::WindowNoState);
}

void  MainWindow::slot_maximized()
{
    setWindowState(Qt::WindowMaximized);
}

This is my result:

enter image description here

But This is the better option for what you are doing:

Please clone the repo from GitHub(it has more changes):

https://github.com/parisa-hr/Draggable-and-Movable-Frameless-Window

This is the result:

enter image description here

Upvotes: 1

Noscere
Noscere

Reputation: 419

Just looking at the name of your co-ordinate variable

    mLastMousePosition

which you use to restore the window after it is no longer maximised:

        // The window is maximized, user has leftbutton down, and is 
        // trying to move it.
        if ((maximized) && (event->buttons().testFlag(Qt::LeftButton) && mMoving))
        {
            slot_restored();
            maximized = false;
            mLastMousePosition = mLastMousePositionBeforeMaximize;
        }

Are you are using the mouse pointer position to put the window back onto the screen? If so, you're using the wrong data. (Although looking at the slot_restored() function, you're not actually providing any co-ordinates?)

To explain what I meant in my comment, each window has its own position, for example if the window is in the very top left corner, then its co-ordinates will be 0,0 - irrelevant of where the mouse pointer is. If you then retored the window to the mLastMousePosition, this could be anywhere along the title bar of the window (even as far as close to the top right corner, restoring your window so that it is almost off the screen).

You might be saving the mouse position for other purposes? It's not clear from your code snippet - but you probably want to be saving the window position before it gets maximised, so that you can restore it again later ...

This might be of great help for you:

Save Window Widget Geometry and Restore QWidget Gemoetry

Upvotes: 0

Related Questions