简体   繁体   English

当鼠标位于 Qt 中窗口的自定义小部件上时,如何移动整个窗口?

[英]How to move the whole window when mouse is on the window's custom widget in Qt?

Let's say I have a custom widget and add it to the main window in qt.假设我有一个自定义小部件并将其添加到 qt 的主窗口中。

在此处输入图片说明

As you can see, the red area is the custom widget.如您所见,红色区域是自定义小部件。 What I want to do is when the mouse is pressed in the red area and moved, the whole window will move as well.我想要做的是当鼠标在红色区域按下并移动时,整个窗口也会移动。

I know how to simply implement mousePressEvent and mouseMoveEvent ;我知道如何简单地实现mousePressEventmouseMoveEvent but when dealing with a window with the custom widget, I do not know how to move the whole window when mouse is pressed on the custom widget.但是在处理带有自定义小部件的窗口时,我不知道如何在自定义小部件上按下鼠标时移动整个窗口。

Also I want to mention that I only want the window movable when mouse is pressed and moved in the red area, and when mouse is pressed and moved in the rest part of the main window area, nothing will happen.另外我想提一下,我只希望在红色区域按下鼠标并移动时窗口可移动,而当鼠标在主窗口区域的其余部分按下并移动时,什么都不会发生。

This is what my CustomWidget class looks like:这是我的CustomWidget类的样子:

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);
}

In case you wonder why I want to do this, in my app, I hid the title bar and drew a custom title bar by myself.如果你想知道我为什么要这样做,在我的应用程序中,我隐藏了标题栏并自己绘制了一个自定义标题栏。 But the window is not movable, so I want to make the whole window movable when mouse is pressed and moved on the title bar.但是窗口是不可移动的,所以我想让整个窗口在鼠标在标题栏上按下和移动时都可以移动。
Hope I explained myself clearly.希望我清楚地解释了自己。

To move the window from any widget it is necessary to be able to access the window, and for this we use the method window() that returns the top level, it is not necessary to separate the coordinates x() and y() , the following code implements the solution:要从任何小部件移动窗口,必须能够访问该窗口,为此我们使用返回顶层的window()方法,不必将坐标x()y()分开,以下代码实现了解决方案:

customwidget.h自定义小部件.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 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);
}

If you are working on Windows, can use it:如果您在 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;
}

I have implemented the above in one of my github project https://github.com/VinuRajaKumar/AVR-HEX-Viewer where QLabel is used as TitleBar for the window.我已经在我的 github 项目https://github.com/VinuRajaKumar/AVR-HEX-Viewer之一中实现了上述内容,其中 QLabel 用作窗口的标题栏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM