From 13c6a06c9b6e78fd522c6f737f0d06c38cb5b22b Mon Sep 17 00:00:00 2001 From: tianduanrui Date: Sun, 22 Sep 2019 19:22:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AD=90=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E5=99=A8=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/exquisite/qqtbodymover.h | 3 + src/exquisite/qqtbodymover_p.h | 2 +- src/exquisite/qqtbodyresizer_p.h | 2 +- src/exquisite/qqtchildbodymover.cpp | 119 ++++++++++++++++++++++++++++ src/exquisite/qqtchildbodymover.h | 45 +++++++++++ src/qqt_source.pri | 12 ++- 6 files changed, 179 insertions(+), 4 deletions(-) create mode 100644 src/exquisite/qqtchildbodymover.cpp create mode 100644 src/exquisite/qqtchildbodymover.h diff --git a/src/exquisite/qqtbodymover.h b/src/exquisite/qqtbodymover.h index 318009be..ef2826e0 100644 --- a/src/exquisite/qqtbodymover.h +++ b/src/exquisite/qqtbodymover.h @@ -23,6 +23,9 @@ * 在鼠标move的时候,截获鼠标消息,使窗口移动。 * 支持所有QWidget及其子类,不支持QMainWindow。 * 支持windows、macOS、Linux、e-linux等操作系统。 + * + * 无论应用于主窗口、子窗口都会导致窗口整体移动, + * 在Windows、macOS、Linux等系统下表现一致。 */ class QQtBodyMoverPrivate; class QQTSHARED_EXPORT QQtBodyMover : public QObject diff --git a/src/exquisite/qqtbodymover_p.h b/src/exquisite/qqtbodymover_p.h index 02dc017e..d0b91fd1 100644 --- a/src/exquisite/qqtbodymover_p.h +++ b/src/exquisite/qqtbodymover_p.h @@ -16,7 +16,7 @@ public: QMargins& margins(); const QMargins& margins() const; -public: +protected: virtual void mousePressEvent ( QMouseEvent* event, QWidget* target = 0 ); virtual void mouseReleaseEvent ( QMouseEvent* event, QWidget* target = 0 ); virtual void mouseMoveEvent ( QMouseEvent* event, QWidget* target = 0 ); diff --git a/src/exquisite/qqtbodyresizer_p.h b/src/exquisite/qqtbodyresizer_p.h index 908603ad..c220a027 100644 --- a/src/exquisite/qqtbodyresizer_p.h +++ b/src/exquisite/qqtbodyresizer_p.h @@ -28,7 +28,7 @@ public: QMargins& margins(); const QMargins& margins() const; -public: +protected: virtual void mousePressEvent ( QMouseEvent* event, QWidget* target = 0 ); virtual void mouseReleaseEvent ( QMouseEvent* event, QWidget* target = 0 ); virtual void mouseMoveEvent ( QMouseEvent* event, QWidget* target = 0 ); diff --git a/src/exquisite/qqtchildbodymover.cpp b/src/exquisite/qqtchildbodymover.cpp new file mode 100644 index 00000000..ee1d0c37 --- /dev/null +++ b/src/exquisite/qqtchildbodymover.cpp @@ -0,0 +1,119 @@ +#include + +QQtChildBodyMover::QQtChildBodyMover ( QObject* parent ) : QObject ( parent ) +{ + bMousePressed = false; + m_margins = QMargins ( 10, 10, 10, 10 ); + +} + +QQtChildBodyMover::~QQtChildBodyMover() {} + +QMargins& QQtChildBodyMover::margins() +{ + return m_margins; +} + +void QQtChildBodyMover::mousePressEvent ( QMouseEvent* event, QWidget* target ) +{ + Q_ASSERT ( target ); + + //以下代码用来过滤边缘的margin。 +#if 1 + //maptoGlobal(rect()) 与 globalPos 对比 + QRect rectMustIn = QRect ( target->mapToGlobal ( target->rect().topLeft() ), target->mapToGlobal ( target->rect().bottomRight() ) ); +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) + QRect rectMustNotIn = rectMustIn.adjusted ( m_margins.left(), m_margins.top(), m_margins.right(), m_margins.bottom() ); +#else + QRect rectMustNotIn = rectMustIn.marginsRemoved ( m_margins ); +#endif + QPoint cursorPos = event->globalPos(); + //经过测试,这种方法,在子窗口、root窗口,得到的数据完全正常。 + //pline() << target->geometry() << rectMustIn + // << rectMustIn.contains ( event->globalPos() ) << rectMustNotIn.contains ( event->globalPos() ); +#endif + + if ( target->isMaximized() || + !target->isActiveWindow() || + !rectMustIn.contains ( cursorPos ) || + !rectMustNotIn.contains ( cursorPos ) ) + { + event->ignore(); + return; + } + + if ( event->button() == Qt::LeftButton ) + { + bMousePressed = true; + pressedPoint = event->globalPos(); + } + event->accept(); +} + +void QQtChildBodyMover::mouseReleaseEvent ( QMouseEvent* event, QWidget* target ) +{ + bMousePressed = false; + event->accept(); +} + +void QQtChildBodyMover::mouseMoveEvent ( QMouseEvent* event, QWidget* target ) +{ + Q_ASSERT ( target ); + + QWidget* win = target->window(); + if ( bMousePressed && !win->isMaximized() ) + { + QPoint p1 = event->globalPos(); + QPoint pxy = p1 - pressedPoint; + pressedPoint = p1; + + QPoint p0 = target->geometry().topLeft(); + QPoint p2 = p0 + pxy; + target->move ( p2 ); + } + event->accept(); +} + + +bool QQtChildBodyMover::eventFilter ( QObject* watched, QEvent* event ) +{ + //过滤掉不是QWidget + if ( !watched->inherits ( "QWidget" ) ) + return QObject::eventFilter ( watched, event ); + + //修复 paint bug + /*fix the parent handled bug terminally*/ + if ( event->type() == QEvent::Paint ) + return QObject::eventFilter ( watched, event ); + + //修复鼠标穿透。 + bool atti = ( qobject_cast ( watched ) )->testAttribute ( Qt::WA_TransparentForMouseEvents ); + if ( atti ) + return QObject::eventFilter ( watched, event ); + + switch ( event->type() ) + { + case QEvent::MouseButtonPress: + { + QMouseEvent* e = ( QMouseEvent* ) event; + mousePressEvent ( e, qobject_cast ( watched ) ); + return false; + } + case QEvent::MouseButtonRelease: + { + QMouseEvent* e = ( QMouseEvent* ) event; + mouseReleaseEvent ( e, qobject_cast ( watched ) ); + return false; + } + case QEvent::MouseMove: + { + QMouseEvent* e = ( QMouseEvent* ) event; + mouseMoveEvent ( e, qobject_cast ( watched ) ); + return false; + } + default: + break; + } + + return QObject::eventFilter ( watched, event ); +} diff --git a/src/exquisite/qqtchildbodymover.h b/src/exquisite/qqtchildbodymover.h new file mode 100644 index 00000000..ae7b5be3 --- /dev/null +++ b/src/exquisite/qqtchildbodymover.h @@ -0,0 +1,45 @@ +#ifndef QQTCHILDBODYMOVER_H +#define QQTCHILDBODYMOVER_H + +#include +#include +#include +#include + +#include + +/** + * @brief The QQtChildBodyMover class + * 摁住子窗体就能在父窗体里移动 + * + * 允许使用这一个句柄为多个窗口安装,各自独立工作,互不干扰。 + * 只能应用于子窗口 + * 在Windows、macOS、Linux等系统下表现一致。 + */ +class QQTSHARED_EXPORT QQtChildBodyMover : public QObject +{ + Q_OBJECT +public: + QQtChildBodyMover ( QObject* parent = 0 ); + virtual ~QQtChildBodyMover(); + + QMargins& margins(); + +protected: + virtual void mousePressEvent ( QMouseEvent* event, QWidget* target = 0 ); + virtual void mouseReleaseEvent ( QMouseEvent* event, QWidget* target = 0 ); + virtual void mouseMoveEvent ( QMouseEvent* event, QWidget* target = 0 ); + + // QObject interface +public: + virtual bool eventFilter ( QObject* watched, QEvent* event ) override; + +private: + bool bMousePressed; + QPoint pressedPoint; + + QMargins m_margins; +}; + + +#endif // QQTCHILDBODYMOVER_H diff --git a/src/qqt_source.pri b/src/qqt_source.pri index b19ca8a8..f7ae66ff 100644 --- a/src/qqt_source.pri +++ b/src/qqt_source.pri @@ -343,7 +343,7 @@ contains (DEFINES, __NETWORKSUPPORT__) { contains (DEFINES, __EXQUISITE__) { #exquisite - #窗体移动 + #窗体整体移动 对父、子窗体均可使用,跨平台特征好 HEADERS += \ $$PWD/exquisite/qqtbodymover.h \ $$PWD/exquisite/qqtbodymover_p.h @@ -351,7 +351,7 @@ contains (DEFINES, __EXQUISITE__) { $$PWD/exquisite/qqtbodymover.cpp \ $$PWD/exquisite/qqtbodymover_p.cpp - #窗体大小。一般用于无边框窗体 + #窗体大小。一般用于无边框窗体。父、子窗体均可使用 HEADERS += \ $$PWD/exquisite/qqtbodyresizer.h \ $$PWD/exquisite/qqtbodyresizer_p.h @@ -359,6 +359,14 @@ contains (DEFINES, __EXQUISITE__) { $$PWD/exquisite/qqtbodyresizer.cpp \ $$PWD/exquisite/qqtbodyresizer_p.cpp + #子窗体在父窗体里移动 只应用于子窗体,不能应用于主窗体 + add_file($$PWD/exquisite/qqtchildbodymover.h) + add_file($$PWD/exquisite/qqtchildbodymover.cpp) + HEADERS += \ + $$PWD/exquisite/qqtchildbodymover.h + SOURCES += \ + $$PWD/exquisite/qqtchildbodymover.cpp + #不规则形状的控件 contains (DEFINES, __IRREGULARWIDGETS__) { SOURCES += \