【Qt坐标系统】 全局坐标和相对坐标

QMouseEvent 中有两类坐标系统,一类是窗口坐标,一类是显示器坐标。以下主要介绍mapFromGlobalmapFromGlobal等坐标转换相关的函数。

Widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QLabel>
#include <QMouseEvent>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QMouseEvent>
#include <QDebug>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

protected:
    void mouseMoveEvent(QMouseEvent *e); // 鼠标移动事件
    bool eventFilter(QObject *obj, QEvent *event); // 事件过滤器

private:
    QWidget *m_pSubWidget; // 子窗口

    QLabel *m_pLabMousePos; // QMouseEvent::pos()
    QLabel *m_pLabMouseGPos; // QMouseEvent::globalPos()
    QLabel *m_pLabCursorPos; // QCursor::pos()
    QLabel *m_pLabMapToGlobal;// QWidget::mapToGlobal(pos)
    QLabel *m_pLabMapFromGlobal; // QWidget::mapFromGlobal(pos)
    QLabel *m_pLabMapToParent; // QWidget::mapToParent(pos)
    QLabel *m_pLabMapFromParent; // QWidget::mapFromParent(pos)
    QLabel *m_pLabMapTo; // QWidget::mapTo(const QWidget * parent, const QPoint & pos)
};
#endif // WIDGET_H

Widget.cpp:

#include "widget.h"

#define STYLE "QLabel{color:green;font-size:18px;}"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    this->setFixedSize(800, 600);

    // 初始化窗口部件
    m_pLabMousePos = new QLabel;
    m_pLabMouseGPos = new QLabel;
    m_pLabCursorPos = new QLabel;
    m_pLabMapToGlobal = new QLabel;
    m_pLabMapFromGlobal = new QLabel;
    m_pLabMapToParent = new QLabel;
    m_pLabMapFromParent = new QLabel;
    m_pLabMapTo = new QLabel;
    m_pLabMousePos->setText("QMouseEvent::pos(): ");
    m_pLabMouseGPos->setText("QMouseEvent::pos(): ");
    m_pLabCursorPos->setText("QCursor::pos(): ");
    m_pLabMapToGlobal->setText("QWidget::mapToGlobal(pos): ");
    m_pLabMapFromGlobal->setText("QWidget::mapFromGlobal(pos): ");
    m_pLabMapToParent->setText("QWidget::mapToParent(pos): ");
    m_pLabMapFromParent->setText("QWidget::mapFromParent(pos): ");
    m_pLabMapTo->setText("QWidget::mapTo(parent,pos): ");
    m_pLabMousePos->setStyleSheet(STYLE);
    m_pLabMouseGPos->setStyleSheet(STYLE);
    m_pLabCursorPos->setStyleSheet(STYLE);
    m_pLabMapToGlobal->setStyleSheet(STYLE);
    m_pLabMapFromGlobal->setStyleSheet(STYLE);
    m_pLabMapToParent->setStyleSheet(STYLE);
    m_pLabMapFromParent->setStyleSheet(STYLE);
    m_pLabMapTo->setStyleSheet(STYLE);

    // 子窗口
    m_pSubWidget = new QWidget;
    m_pSubWidget->setFixedSize(width()/2, height()/2);
    m_pSubWidget->setStyleSheet("background: gray;");
    m_pSubWidget->installEventFilter(this); // 安装事件过滤器

    // Lable布局
    QVBoxLayout *pVLayoutLab = new QVBoxLayout;
    pVLayoutLab->addWidget(m_pLabMousePos);
    pVLayoutLab->addWidget(m_pLabMouseGPos);
    pVLayoutLab->addWidget(m_pLabCursorPos);
    pVLayoutLab->addWidget(m_pLabMapToGlobal);
    pVLayoutLab->addWidget(m_pLabMapFromGlobal);
    pVLayoutLab->addWidget(m_pLabMapToParent);
    pVLayoutLab->addWidget(m_pLabMapFromParent);
    pVLayoutLab->addWidget(m_pLabMapTo);
    pVLayoutLab->addStretch();
    pVLayoutLab->setSpacing(12);
    pVLayoutLab->setContentsMargins(30, 200, 30, 30);
    // 主布局
    QHBoxLayout *pHLayoutMain = new QHBoxLayout(this);
    pHLayoutMain->addWidget(m_pSubWidget);
    pHLayoutMain->addLayout(pVLayoutLab);
}

Widget::~Widget()
{
}

// 鼠标移动事件
void Widget::mouseMoveEvent(QMouseEvent *e)
{
    // 返回相对这个widget(重载了QMouseEvent的widget)的位置
    m_pLabMousePos->setText(QString("QMouseEvent::pos(): %1,%2")\
                            .arg(e->pos().x()).arg(e->pos().y()));
    // 窗口坐标,这个是返回鼠标的全局坐标
    m_pLabMouseGPos->setText(QString("QMouseEvent::globalPos(): %1,%2")\
                             .arg(e->globalPos().x()).arg(e->globalPos().y()));
    // 返回相对显示器的全局坐标
    m_pLabCursorPos->setText(QString("QCursor::pos(): %1,%2")\
                             .arg(QCursor::pos().x()).arg(QCursor::pos().y()));
    // 将窗口坐标转换成显示器坐标
    m_pLabMapToGlobal->setText(QString("QWidget::mapToGlobal(pos): %1,%2")\
                             .arg(this->mapToGlobal(e->pos()).x()).arg(this->mapToGlobal(e->pos()).y()));
    // 将显示器坐标转换成窗口坐标
    m_pLabMapFromGlobal->setText(QString("QWidget::mapFromGlobal(pos): %1,%2")\
                                 .arg(this->mapFromGlobal(QCursor::pos()).x()).arg(this->mapFromGlobal(QCursor::pos()).y()));
    // 将父类窗口坐标转换成当前窗口坐标
    m_pLabMapFromParent->setText(QString("QWidget::mapFromParent(pos): %1,%2")\
                             .arg(m_pSubWidget->mapFromParent(e->pos()).x()).arg(m_pSubWidget->mapFromParent(e->pos()).y()));

}

//事件过滤器
bool Widget::eventFilter(QObject *obj, QEvent *event)
{
    // 判断部件
    if (obj == m_pSubWidget)
    {
        // 判断事件
        if (event->type() == QEvent::MouseMove)
        {
            // 将event强制转换为发生的事件的类型
            QMouseEvent *e = static_cast<QMouseEvent*>(event);
            // 将窗口坐标获得的pos转换成父类widget的坐标
            // 实际测试,与父窗口的相对显示器的全局坐标相等
            m_pLabMapToParent->setText(QString("QWidget::mapToParent(pos): %1,%2")\
                                     .arg(this->mapToParent(e->pos()).x()).arg(this->mapToParent(e->pos()).y()));

            // 将当前窗口坐标转换成指定parent坐标
            m_pLabMapTo->setText(QString("QWidget::mapTo(parent,pos): %1,%2")\
                                     .arg(m_pSubWidget->mapTo(this, e->pos()).x()).arg(m_pSubWidget->mapTo(this, e->pos()).y()));

            return true;
        }
        else // 如果是其他事件,可以进行进一步的处理
        {
            return false;
        }
    }

    else return QWidget::eventFilter(obj, event);
}

程序运行如下:

v6D5b6.png


posted @ 2022-06-09 16:29  fengMisaka  阅读(71)  评论(0编辑  收藏  举报