【问题标题】:Qt 5, get the mouse position in a screenQt 5,获取鼠标在屏幕中的位置
【发布时间】:2015-08-16 21:39:28
【问题描述】:

首先,我想提一下,我发现了相关帖子How to get the mouse position on the screen in Qt?,但它对我来说“只是没有用”。我做了一些测试,结果并没有达到我的预期,所以我决定发一个新帖子来谈谈我所做的测试并寻找替代解决方案。

这是我用来做测试的代码:

QScreen *screen0 = QApplication::screens().at(0);
QScreen *screen1 = QApplication::screens().at(1);

printf("screen0 %s \n", screen0->name().toStdString().c_str());
printf("screen1 %s \n", screen1->name().toStdString().c_str());

// Position on first screen.
QPoint pos0 = QCursor::pos(screen0);

// Position on second screen.
QPoint pos1 = QCursor::pos(screen1);

printf("pos 0: %d, %d \n", pos0.x(), pos0.y());
printf("pos 1: %d, %d \n", pos1.x(), pos1.y());

// Get position without screen.
QPoint pos = QCursor::pos();
printf("pos: %d, %d \n", pos.x(), pos.y());

我所期待的是,只有一个屏幕会返回有效位置,因为光标只在一个屏幕上,而不是在两个屏幕上。但事实并非如此,这两个位置(pos0pos1)具有完全相同的值,正如我们在输出中看到的那样:

screen0 DVI-D-0 
screen1 HDMI-0 
pos 0: 1904, 1178 
pos 1: 1904, 1178 
pos: 1904, 1178 

由于两个位置的值相同,我无法知道光标在哪个屏幕上。我不知道这是正常行为还是错误,因为文档没有说明当屏幕参数不是鼠标所在的屏幕时会发生什么。

我的想法是打开/启动一个应用程序(由必须检测所选屏幕的 Qt 守护程序执行)到鼠标所在的屏幕。我知道使用 libX11 是可能的,因为我过去做过,但我需要使用 Qt 5,我不知道如何使用 Qt 检测选定的屏幕。

我还进行了其他测试,使用 QApplicationQDesktopWidget 类但没有运气。

【问题讨论】:

  • 您使用的是虚拟桌面吗?双头?

标签: c++ qt qt5 multiscreen


【解决方案1】:

这真的很奇怪。作为一种解决方法,您可以尝试以下方法:

QPoint globalCursorPos = QCursor::pos();
int mouseScreen = qApp->desktop()->screenNumber(globalCursorPos);

现在您知道光标在哪个屏幕。然后您可以在该屏幕中找到光标位置:

QRect mouseScreenGeometry = qApp->desktop()->screen(mouseScreen)->geometry();
QPoint localCursorPos = globalCursorPos - mouseScreenGeometry.topLeft();

【讨论】:

  • 我试过了,但它总是返回屏幕 0。即使你从 screen1 取点(使用 pos(QScreen*)),它也会返回 0。
  • 我正在使用 Getoo,将 KDE 和 Awesome 作为窗口管理器。可能是配置问题。 Rafael,你能分享一下你执行的输出和代码吗?
  • 可能是 Qt 错误。仅供参考:我尝试了您在问题中所做的事情,但它在 Windows 上也不起作用。我在 pos(QScreen*) 上得到了相同的坐标值,不管它是在哪个屏幕上给出的以及光标在哪里。抱歉,我帮不上忙。
  • 您的解决方案对我有用。你是对的QCursor::pos(QScreen*) 似乎无法正常工作(仍然)。
【解决方案2】:

这似乎是一个微不足道的解决方案,但在我的 KDE 上它可以工作(我最初遇到了同样的问题)。 如果您想确定相对于小部件的本地鼠标坐标(这将以设备像素为单位,并且我相信相对于小部件的左上角),您可以使用

QWidget::mapFromGlobal(QCursor::pos());

即拨打this->mapFromGlobal

【讨论】:

    【解决方案3】:

    要确定您在哪个屏幕上,您可以遍历QGuiApplication::screens() 并检查光标是否适合屏幕的geometry

    这里是一个计算原生光标位置的更复杂的示例(注意使用高 DPI 屏幕所需的额外工作):

    QPoint getNativeCursorPosition()
    {
        QPoint pos = cursorPosToNative(QCursor::pos());
    
        // Cursor positions from Qt are calculated in a strange way, the offset to
        // the origin of the current screen is in device-independent pixels while
        // the origin itself is native!
    
        for (QScreen *screen : QGuiApplication::screens()) {
            QRect screenRect = screen->geometry();
            if (screenRect.contains(pos)) {
                QPoint origin = screenRect.topLeft();
                return origin + (pos - origin) * screen->devicePixelRatio();
            }
        }
    
        // should not happen, but try to find a good fallback.
        return pos * qApp->devicePixelRatio();
    }
    

    【讨论】:

    • 在这段代码中,我认为 cursorPos 应该重命名为 pos。
    • 这个cursorPosToNative 函数需要哪个头文件 - 它似乎在 Qt 5.9.3 中不存在?
    • @Vertigo 应该有一种独立于平台的方法来计算它,但为了简单起见,我没有实现它,而是直接查询本机 API。参见例如github.com/KDE/spectacle/commit/…
    【解决方案4】:

    这可能对您有用吗? 它对我有用

    QDesktopWidget *widget = QApplication::desktop(); QPosition globalCursorPosition = widget->cursor().pos();

    【讨论】:

      【解决方案5】:

      不过,它似乎不能用 Qt 完成(至少在我的系统配置中,而且似乎在 Windows 中也是如此)我决定使用 libX11 来实现该实现,这就像魅力一样。

      这不是一个理想的解决方案,因为我只想使用 Qt,但它确实有效。

      【讨论】:

        【解决方案6】:

        使用 QML,您可以使用 Screen QML 类型的属性:

        Screen.virtualX : 虚拟桌面中屏幕的 x 坐标。

        Screen.virtualY : 虚拟桌面中屏幕的 y 坐标。

        import QtQuick 2.6
        import QtQuick.Window 2.2
        
        console.log("Pos x : " + Screen.virtualX )
        console.log("Pos y : " + Screen.virtualY )
        

        这适用于单屏幕以及多显示器系统。

        【讨论】:

          【解决方案7】:

          我最近在 Qt 5.15 + Windows + 混合 DPI 上遇到了类似的问题,需要在 QWindow 对象中解决这个问题。

          QScreen* primaryScreen = QGuiApplication::primaryScreen();
          QScreen* thisScreen = screen();
          qreal primaryDPR = primaryScreen->devicePixelRatio();
          qreal thisDPR = thisScreen->devicePixelRatio();
          qreal scale = thisDPR / primaryDPR;
          QPoint pos = scale  * QCursor::pos();
          

          我不确定这是否适用于其他平台。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-02-28
            相关资源
            最近更新 更多