Reputation: 399
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.
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:
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
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:
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:
Upvotes: 1
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