web-dev-qa-db-fra.com

Qt 5, obtenir la position de la souris sur un écran

Tout d'abord, je voudrais mentionner que j'ai trouvé ce message connexe Comment obtenir la position de la souris sur l'écran dans Qt? mais cela "n'a tout simplement pas fonctionné" pour moi. J'ai fait quelques tests, et les résultats n'ont pas fonctionné comme prévu, j'ai donc décidé de faire un nouveau post pour parler du test que j'ai fait et pour trouver une solution alternative.

C'est le code que j'ai utilisé pour faire le test:

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

Ce que j'attendais, c'est qu'un seul écran retournerait une position valide, car le curseur n'est que sur un écran, pas sur les deux. Mais ce n'est pas le cas, les deux positions (pos0 et pos1) a exactement la même valeur, comme on peut le voir sur la sortie:

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

Étant donné que les deux positions ont les mêmes valeurs, je ne peux pas savoir à quel écran se trouve le curseur. Je ne sais pas si c'est un comportement normal ou un bug, car la documentation ne dit pas ce qui se passe lorsque l'argument écran n'est pas l'écran où se trouve la souris.

Mon idée, c'est d'ouvrir/lancer une application (exécutée par un démon Qt qui doit détecter l'écran sélectionné) sur l'écran où se trouve la souris. Je sais qu'avec libX11 c'est possible, parce que je l'ai fait dans le passé, mais j'ai besoin de travailler avec Qt 5, et je ne peux pas comprendre comment détecter l'écran sélectionné avec Qt.

J'ai également fait d'autres tests, en utilisant les classes QApplication et QDesktopWidget sans succès.

13
armitage

C'est vraiment bizarre. Comme solution de contournement, vous pouvez essayer ceci:

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

Vous savez maintenant dans quel écran se trouve le curseur. Ensuite, vous pouvez trouver la position du curseur dans cet écran en procédant comme suit:

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

Cela peut sembler être une solution triviale, mais sur mon KDE, cela fonctionne (j'ai rencontré les mêmes problèmes à l'origine). Si vous souhaitez déterminer les coordonnées de la souris locale par rapport à un widget (ce sera en pixels de l'appareil et par rapport au coin supérieur gauche du widget, je crois), vous pouvez utiliser

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

c'est-à-dire appeler this->mapFromGlobal.

4
GPMueller

Pour savoir sur quel écran vous vous trouvez, vous pouvez parcourir it QGuiApplication::screens() et vérifier si le curseur tient dans géométrie de l'écran.

Voici un exemple plus complexe pour calculer la position native du curseur (notez le travail supplémentaire nécessaire pour travailler avec les écrans haute résolution):

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
Lekensteyn

Sice il semble que cela ne peut pas être fait avec Qt (au moins avec ma configuration système, et il semble que même sous Windows), j'ai décidé d'utiliser le libX11 pour faire cette implémentation, qui fonctionne comme un charme.

Ce n'est pas une solution idéale car je voulais seulement utiliser Qt, mais ça marche.

0
armitage

Cela peut fonctionner pour vous? Ça l'a fait pour moi

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

0
samarth