Qt 5, получить положение мыши на экране

Прежде всего, я хотел бы отметить, что я нашел этот пост Как получить положение мыши на экране в 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());

Я ожидал, что только один экран вернет правильную позицию, поскольку курсор находится только на одном экране, а не на обоих. Но это не тот случай, обе позиции (pos0 а также pos1) имеет точно такое же значение, как мы видим на выходе:

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

Поскольку обе позиции имеют одинаковые значения, я не могу знать, на каком экране находится курсор. Я не знаю, нормальное ли это поведение или ошибка, так как в документации не сказано, что происходит, когда аргумент экрана не тот экран, где находится мышь.

Моя идея состоит в том, чтобы открыть / запустить приложение (исполняемое демоном Qt, которое должно обнаружить выбранный экран) на экране, где находится мышь. Я знаю что с libx11 это возможно, потому что я делал это в прошлом, но мне нужно работать с Qt 5, и я не могу понять, как сделать обнаружение выбранного экрана с помощью Qt.

Я также сделал другие тесты, используя QApplication а также QDesktopWidget занятия без удачи.

9

Решение

Это действительно странно. В качестве обходного пути вы можете попробовать это:

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

Теперь вы знаете, на каком экране находится курсор. Затем вы можете найти позицию курсора на этом экране, выполнив следующее:

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

Другие решения

Это может показаться тривиальным решением, но на моем KDE оно работает (изначально я сталкивался с такими же проблемами).
Если вы хотите определить локальные координаты мыши относительно виджета (это будет в пикселях устройства и относительно верхнего левого угла виджета, я полагаю), вы можете использовать

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

то есть звонок this->mapFromGlobal,

2

Чтобы выяснить, на каком экране вы находитесь, вы можете выполнить QGuiApplication::screens() и проверьте, помещается ли курсор в геометрия экрана.

Вот более сложный пример для вычисления собственной позиции курсора (обратите внимание на дополнительную работу, необходимую для работы с экранами с высоким разрешением):

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

Так как кажется, что это невозможно сделать с помощью Qt (по крайней мере, с моей конфигурацией системы, и, похоже, также и в Windows), я решил использовать libX11, чтобы сделать эту реализацию, которая работает как шарм.

Это не идеальное решение, потому что я хотел использовать только Qt, но оно работает.

0
По вопросам рекламы [email protected]