Qt - 控件坐标转换
屏幕与窗口
****屏幕坐标(绝对坐标) 窗口坐标(相对坐标)****
坐标的概念:
- 窗口坐标(Window Coordinates):窗口坐标是相对于窗口左上角的坐标。在这个坐标系统中,原点(0,0)位于窗口的左上角,x 轴从左到右增加,y 轴从上到下增加。这意味着,如果你在窗口中的某个位置点击鼠标,那么你得到的鼠标点击事件的坐标就是相对于窗口左上角的坐标。
- 显示器坐标(Screen Coordinates):显示器坐标是相对于整个显示器的坐标。在这个坐标系统中,原点(0,0)位于显示器的左上角,x 轴从左到右增加,y 轴从上到下增加。这意味着,无论你在哪个窗口或者哪个部分的屏幕上点击鼠标,你得到的鼠标点击事件的坐标都是相对于显示器左上角的坐标。
- 父窗口坐标(Parent Coordinates):这是相对于父窗口(如果有的话)的坐标系统。原点(0,0)位于父窗口的左上角。这在处理嵌套窗口或控件时非常有用。
- 场景坐标(Scene Coordinates):这是在 QGraphicsScene 中使用的坐标系统,用于处理图形项的位置和变换。原点(0,0)可以在场景的任何位置,默认在中心 这取决于你如何设置和使用场景。
- 视图坐标(View Coordinates):这是在 QGraphicsView 中使用的坐标系统,用于处理视图滚动和缩放。原点(0,0)位于视图的左上角。
坐标转换:
QPoint QMouseEvent::pos()
//这个只是返回鼠标事件相对这个widget(重载了QMouseEvent的widget)的位置。
QPoint QMouseEvent::globalPos()
//窗口坐标,这个是返回鼠标的全局坐标,相对于屏幕的左上角
QPoint QCursor::pos()
//窗口坐标,这个是返回鼠标的全局坐标,相对于屏幕的左上角
QPoint QWidget::mapToGlobal(const QPoint & pos) const
//将窗口坐标转换成显示器坐标
QPoint QWidget::mapFromGlobal(const QPoint & pos) const
//将显示器坐标转换成窗口坐标
QPoint QWidget::mapToParent(const QPoint & pos) const
//将窗口坐标获得的pos转换成父类widget的坐标
QPoint QWidget::mapFromParent(const QPoint & pos) const
//将父类窗口坐标转换成当前窗口坐标
QPoint QWidget::mapTo(const QWidget * parent, const QPoint & pos) const
//将当前窗口坐标转换成指定parent坐标。
QWidget::pos() : QPoint
//这个属性获得的是当前目前控件在父窗口中的位置
const QPointF & QMouseEvent::screenPos() const和QPoint QMouseEvent::globalPos()
//值相同,但是类型更高精度的QPointF
坐标转换:
补充一些函数:
1、QPoint QWidget::mapToGlobal(const QPoint &pos) const
将小部件坐标转换为全局坐标。mapToGlobal(QPoint(0,0))可以得到小部件左上角像素的全局坐标。
2、QPoint QWidget::mapToParent(const QPoint &pos) const
将小部件坐标转换为父部件坐标。如果小部件没有父部件,则效果与mapToGlobal()相同。
3、QPoint QWidget::mapTo(const QWidget *parent, const QPoint &pos) const
将小部件的坐标转换为父部件的坐标系统,parent不能是0,必须是调用小部件的父部件。
4、QPoint QWidget::mapFromGlobal(const QPoint &pos) const
将全局坐标转换为小部件坐标。
5、QPoint QWidget::mapFromParent(const QPoint &pos) const
将父部件坐标转换为小部件坐标。如果小部件没有父部件,则效果与mapFromGlobal()相同。
6、QPoint QWidget::mapFrom(const QWidget *parent, const QPoint &pos) const
将小部件的坐标pos从父部件的坐标系统转换为小部件的坐标系统。parent不能是0,必须是调用小部件的父部件。
7、QPoint QMouseEvent::pos() const
返回鼠标光标相对于接收事件的小部件的位置。
8、QPoint QMouseEvent::globalPos() const
返回事件发生时鼠标光标的全局位置。
9、const QPointF &QMouseEvent::screenPos() const
以QPointF的形式返回鼠标光标相对于接收事件的屏幕的位置。这个函数是在Qt 5.0中引入的。
代码示例1:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QLabel>
#include <QPushButton>
#include <QMainWindow>
#include <QMouseEvent>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class DraggableButton;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
void mouseMoveEvent(QMouseEvent *event) override;
private slots:
void updateBtnLocation();
private:
Ui::MainWindow *ui;
QLabel* cursorPosLabel = nullptr;
QLabel* cursorGlobalLabel = nullptr;
QLabel* currentViewLabel = nullptr;
QLabel* btnPosLabel = nullptr;
QLabel* btnMapFromParentLabel = nullptr;
QLabel* btnMapToParentLabel = nullptr;
QLabel* btnMapToGlobalLabel = nullptr;
QLabel* btnMapFromGlobalLabel = nullptr;
DraggableButton* dragBtn = nullptr;
};
class DraggableButton : public QPushButton
{
Q_OBJECT
public:
DraggableButton(QWidget *parent = nullptr)
: QPushButton(parent), m_dragging(false) {}
protected:
void mousePressEvent(QMouseEvent *event) override
{
if (event->button() == Qt::LeftButton) {
m_dragging = true;
m_startPosition = event->pos();
}
}
void mouseMoveEvent(QMouseEvent *event) override
{
if (m_dragging)
{
move(mapToParent(event->pos() - m_startPosition));
emit btnMoving();
}
}
void mouseReleaseEvent(QMouseEvent *event) override
{
if (event->button() == Qt::LeftButton) {
m_dragging = false;
}
}
signals:
void btnMoving();
private:
bool m_dragging;
QPoint m_startPosition;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QPushButton"
#include "QLabel"
#include "QMouseEvent"
#include "QVBoxLayout"
#include "qdebug.h"
#include "QWidget"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
this->setObjectName("mianwin");
this->setStyleSheet("#mianwin { border: 5px solid yellow; }");
ui->setupUi(this);
auto widget = new QWidget(this);
widget->setObjectName("view");
widget->setStyleSheet("#view { border: 2px solid red; }");
cursorPosLabel = new QLabel(widget);
cursorGlobalLabel = new QLabel(widget);
currentViewLabel = new QLabel(widget);
btnPosLabel = new QLabel(widget);
btnMapFromParentLabel = new QLabel(widget);
btnMapToParentLabel = new QLabel(widget);
btnMapToGlobalLabel = new QLabel(widget);
btnMapFromGlobalLabel = new QLabel(widget);
dragBtn = new DraggableButton(this);
dragBtn->setText("Drag me!");
dragBtn->setFixedSize(80,40);
QVBoxLayout* vL = new QVBoxLayout(widget);
vL->setSpacing(20);
vL->addWidget(cursorPosLabel);
vL->addWidget(cursorGlobalLabel);
vL->addWidget(currentViewLabel);
vL->addSpacing(50);
vL->addWidget(btnPosLabel);
vL->addWidget(btnMapFromParentLabel);
vL->addWidget(btnMapToParentLabel);
vL->addWidget(btnMapToGlobalLabel);
vL->addWidget(btnMapFromGlobalLabel);
vL->addStretch();
setMouseTracking(true);
setCentralWidget(widget);
connect(dragBtn,&DraggableButton::btnMoving,this,&MainWindow::updateBtnLocation);
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
auto cursorPos = QCursor::pos();
auto cursorGlobal = event->globalPos();
cursorPosLabel->setText(QString("鼠标的全局位置:(x:%1,y:%2)").arg(cursorPos.x()).arg(cursorPos.y()));
cursorGlobalLabel->setText(QString("QMouseEvent事件的globalPos全局位置:(x:%1,y:%2)").arg(cursorGlobal.x()).arg(cursorGlobal.y()));
currentViewLabel->setText(QString("QMouseEvent事件的pos()相对于当前窗口位置:(x:%1,y:%2)").arg(event->pos().x()).arg(event->pos().y()));
}
void MainWindow::updateBtnLocation()
{
btnPosLabel->setText(QString("btn事件的pos()相对于当前父控件位置:(x:%1,y:%2)").arg(dragBtn->pos().x()).arg(dragBtn->pos().y()));
auto dragBtnmapFromParent = dragBtn->mapFromParent(QPoint(0,0));
btnMapFromParentLabel->setText(QString("父窗口QPoint(0,0)位置转为btn的位置:(x:%1,y:%2)").arg(dragBtnmapFromParent.x()).arg(dragBtnmapFromParent.y()));
auto dragBtnmapToParent = dragBtn->mapToParent(QPoint(0,0)+QPoint(dragBtn->width(),dragBtn->height()));
btnMapToParentLabel->setText(QString("btn的QPoint(80,40)相对于当前父控件位置:(x:%1,y:%2)").arg(dragBtnmapToParent.x()).arg(dragBtnmapToParent.y()));
auto dragBtnmapToGlobal = dragBtn->mapToGlobal(QPoint(0,0));
btnMapToGlobalLabel->setText(QString("btn的QPoint(0,0)相对于当前全局位置:(x:%1,y:%2)").arg(dragBtnmapToGlobal.x()).arg(dragBtnmapToGlobal.y()));
auto dragBtnmapFromGlobal = dragBtn->mapFromGlobal(QPoint(0,0));
btnMapFromGlobalLabel->setText(QString("全局QPoint(0,0)位置转为btn的位置:(x:%1,y:%2)").arg(dragBtnmapFromGlobal.x()).arg(dragBtnmapFromGlobal.y()));
}
MainWindow::~MainWindow()
{
delete ui;
}
运行效果:
代码示例2:
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QMoveEvent>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{
ui->setupUi(this);
button = new QPushButton("Click me", this);
button->setGeometry(50, 50, 100, 50);
}
Widget::~Widget()
{
delete ui;
}
//窗口移动事件
void Widget::moveEvent(QMoveEvent *event)
{
qDebug()<<"原来的pos"<<event->oldPos()<<"现在的pos"<<event->pos();
// 转换到全局坐标
QPoint globalPoint = button->mapToGlobal(QPoint(0, 0));
qDebug() << "Global Point:" << globalPoint;
// 转换到父控件坐标
QPoint parentPoint = button->mapToParent(QPoint(0, 0));
qDebug() << "Parent Point:" << parentPoint;
// 从全局坐标转换回控件内部坐标
QPoint mappedGlobalPoint = button->mapFromGlobal(globalPoint);
qDebug() << "Mapped Global Point:" << mappedGlobalPoint;
//button左上角在Widget的坐标
QPoint topLeftPoint = button->geometry().topLeft(); //topLeft返回矩形左上角的位置
qDebug() <<"topLeftPoint: "<<topLeftPoint;
//button右上角在Widget的坐标
QPoint topRightPoint = button->geometry().topRight();//topRight返回矩形右上角的位置
qDebug() <<"topRightPoint: "<<topRightPoint;
QRect geometryRect = this->geometry();//去了标题栏的几何坐标
qDebug()<<"geometryRect: "<<geometryRect;
QRect frameGeometryRect = this->frameGeometry();//加上了标题栏的几何坐标
qDebug()<<"frameGeometryRect: "<<frameGeometryRect;
QRect btn_geometryRect = button->geometry();
qDebug()<<"btn_geometryRect: "<<btn_geometryRect;
QRect btn_frameGeometryRect = button->frameGeometry();
qDebug()<<"btn_frameGeometryRect: "<<btn_frameGeometryRect;
}
运行效果:
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_45882303/article/details/136892019
分类:
Qt
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具