当鼠标在 Qt 中 window 的自定义小部件上时,如何移动整个 window?
How to move the whole window when mouse is on the window's custom widget in Qt?
假设我有一个自定义小部件并将其添加到 qt 中的主要 window。
如您所见,红色区域为自定义控件。我想做的是当鼠标在红色区域按下并移动时,整个window也会移动
我知道如何简单地实现 mousePressEvent
和 mouseMoveEvent
;但是当用自定义小部件处理 window 时,我不知道如何在自定义小部件上按下鼠标时移动整个 window。
我还想提一下,我只希望 window 在红色区域按下并移动鼠标时移动,而在主区域的其余部分按下并移动鼠标时 window ] 区域,什么都不会发生。
这是我的 CustomWidget
class 的样子:
CustomWidget::CustomWidget(QWidget *parent) : QWidget(parent)
{
setFixedSize(50, 50);
setStyleSheet("QWidget { background: red; }");
}
void CustomWidget::paintEvent(QPaintEvent *)
{
QStyleOption opt;
opt.init(this);
QPainter painter(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
}
void CustomWidget::mousePressEvent(QMouseEvent *event)
{
xCoord = event->x();
yCoord = event->y();
}
void CustomWidget::mouseMoveEvent(QMouseEvent *event)
{
move(event->globalX() - xCoord, event->globalY() - yCoord);
}
如果你想知道我为什么要这样做,在我的应用程序中,我隐藏了标题栏并自己绘制了一个自定义标题栏。但是 window 是不可移动的,所以我想在标题栏上按下并移动鼠标时使整个 window 可移动。
希望我解释清楚了。
要从任何小部件移动 window,就必须能够访问 window,为此我们使用 window()
方法 returns top level,不需要把坐标x()
和y()
分开,下面代码实现解决:
customwidget.h
#ifndef CUSTOMWIDGET_H
#define CUSTOMWIDGET_H
#include <QWidget>
class CustomWidget : public QWidget
{
Q_OBJECT
public:
explicit CustomWidget(QWidget *parent = nullptr);
protected:
void paintEvent(QPaintEvent *);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
private:
QPoint startPos;
};
#endif // CUSTOMWIDGET_H
customwidget.cpp
#include "customwidget.h"
#include <QMouseEvent>
#include <QPainter>
#include <QStyleOption>
CustomWidget::CustomWidget(QWidget *parent) : QWidget(parent)
{
setFixedSize(50, 50);
setStyleSheet("QWidget { background: red; }");
}
void CustomWidget::paintEvent(QPaintEvent *)
{
QStyleOption opt;
opt.init(this);
QPainter painter(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
}
void CustomWidget::mousePressEvent(QMouseEvent *event)
{
startPos = event->pos();
QWidget::mousePressEvent(event);
}
void CustomWidget::mouseMoveEvent(QMouseEvent *event)
{
QPoint delta = event->pos() - startPos;
QWidget * w = window();
if(w)
w->move(w->pos() + delta);
QWidget::mouseMoveEvent(event);
}
如果您正在 Windows 上工作,可以使用它:
#include "mywidget.h"
#include <windows.h>
#include <QWindow>
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)
{
}
MyWidget::~MyWidget()
{
}
void MyWidget::mousePressEvent(QMouseEvent* event)
{
if (event->buttons().testFlag(Qt::LeftButton))
{
HWND hWnd = ::GetAncestor((HWND)(window()->windowHandle()->winId()), GA_ROOT);
POINT pt;
::GetCursorPos(&pt);
::ReleaseCapture();
::SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, POINTTOPOINTS(pt));
}
}
void QHexWindow::mousePressEvent(QMouseEvent *event)
{
QLabel *child = static_cast<QLabel*>(childAt(event->pos()));
if (child!=mTitleBar) //mTitlebar is the QLabel on which we want to implement window drag
{
return;
}
isMousePressed = true;
mStartPos = event->pos();
}
void QHexWindow::mouseMoveEvent(QMouseEvent *event)
{
if(isMousePressed)
{
QPoint deltaPos = event->pos() - mStartPos;
this->move(this->pos()+deltaPos);
}
}
void QHexWindow::mouseReleaseEvent(QMouseEvent *event)
{
QLabel *child = static_cast<QLabel*>(childAt(event->pos()));
if (child!=mTitleBar)
{
return;
}
isMousePressed = false;
}
我已经在我的一个 github 项目 https://github.com/VinuRajaKumar/AVR-HEX-Viewer 中实现了上述内容,其中 QLabel 被用作 window.
的标题栏
假设我有一个自定义小部件并将其添加到 qt 中的主要 window。
如您所见,红色区域为自定义控件。我想做的是当鼠标在红色区域按下并移动时,整个window也会移动
我知道如何简单地实现 mousePressEvent
和 mouseMoveEvent
;但是当用自定义小部件处理 window 时,我不知道如何在自定义小部件上按下鼠标时移动整个 window。
我还想提一下,我只希望 window 在红色区域按下并移动鼠标时移动,而在主区域的其余部分按下并移动鼠标时 window ] 区域,什么都不会发生。
这是我的 CustomWidget
class 的样子:
CustomWidget::CustomWidget(QWidget *parent) : QWidget(parent)
{
setFixedSize(50, 50);
setStyleSheet("QWidget { background: red; }");
}
void CustomWidget::paintEvent(QPaintEvent *)
{
QStyleOption opt;
opt.init(this);
QPainter painter(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
}
void CustomWidget::mousePressEvent(QMouseEvent *event)
{
xCoord = event->x();
yCoord = event->y();
}
void CustomWidget::mouseMoveEvent(QMouseEvent *event)
{
move(event->globalX() - xCoord, event->globalY() - yCoord);
}
如果你想知道我为什么要这样做,在我的应用程序中,我隐藏了标题栏并自己绘制了一个自定义标题栏。但是 window 是不可移动的,所以我想在标题栏上按下并移动鼠标时使整个 window 可移动。
希望我解释清楚了。
要从任何小部件移动 window,就必须能够访问 window,为此我们使用 window()
方法 returns top level,不需要把坐标x()
和y()
分开,下面代码实现解决:
customwidget.h
#ifndef CUSTOMWIDGET_H
#define CUSTOMWIDGET_H
#include <QWidget>
class CustomWidget : public QWidget
{
Q_OBJECT
public:
explicit CustomWidget(QWidget *parent = nullptr);
protected:
void paintEvent(QPaintEvent *);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
private:
QPoint startPos;
};
#endif // CUSTOMWIDGET_H
customwidget.cpp
#include "customwidget.h"
#include <QMouseEvent>
#include <QPainter>
#include <QStyleOption>
CustomWidget::CustomWidget(QWidget *parent) : QWidget(parent)
{
setFixedSize(50, 50);
setStyleSheet("QWidget { background: red; }");
}
void CustomWidget::paintEvent(QPaintEvent *)
{
QStyleOption opt;
opt.init(this);
QPainter painter(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
}
void CustomWidget::mousePressEvent(QMouseEvent *event)
{
startPos = event->pos();
QWidget::mousePressEvent(event);
}
void CustomWidget::mouseMoveEvent(QMouseEvent *event)
{
QPoint delta = event->pos() - startPos;
QWidget * w = window();
if(w)
w->move(w->pos() + delta);
QWidget::mouseMoveEvent(event);
}
如果您正在 Windows 上工作,可以使用它:
#include "mywidget.h"
#include <windows.h>
#include <QWindow>
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)
{
}
MyWidget::~MyWidget()
{
}
void MyWidget::mousePressEvent(QMouseEvent* event)
{
if (event->buttons().testFlag(Qt::LeftButton))
{
HWND hWnd = ::GetAncestor((HWND)(window()->windowHandle()->winId()), GA_ROOT);
POINT pt;
::GetCursorPos(&pt);
::ReleaseCapture();
::SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, POINTTOPOINTS(pt));
}
}
void QHexWindow::mousePressEvent(QMouseEvent *event)
{
QLabel *child = static_cast<QLabel*>(childAt(event->pos()));
if (child!=mTitleBar) //mTitlebar is the QLabel on which we want to implement window drag
{
return;
}
isMousePressed = true;
mStartPos = event->pos();
}
void QHexWindow::mouseMoveEvent(QMouseEvent *event)
{
if(isMousePressed)
{
QPoint deltaPos = event->pos() - mStartPos;
this->move(this->pos()+deltaPos);
}
}
void QHexWindow::mouseReleaseEvent(QMouseEvent *event)
{
QLabel *child = static_cast<QLabel*>(childAt(event->pos()));
if (child!=mTitleBar)
{
return;
}
isMousePressed = false;
}
我已经在我的一个 github 项目 https://github.com/VinuRajaKumar/AVR-HEX-Viewer 中实现了上述内容,其中 QLabel 被用作 window.
的标题栏