I need to write an application that parses the pixel of the screen when I click on any position, OpenSuse OS.
There is an extended root window class:

class DesktopMouseGrabber : public QDesktopWidget { public: QMainWindow* main_window; DesktopMouseGrabber(QMainWindow *window_) : QDesktopWidget(), main_window(window_) {} void mousePressEvent(QMouseEvent *e); }; void DesktopMouseGrabber::mousePressEvent(QMouseEvent *e) { // событиС ΠΊΠ»ΠΈΠΊΠ° ΠΏΠΎ Π²ΠΈΠ΄ΠΆΠ΅Ρ‚Ρƒ QApplication::postEvent(main_window, e); } 

And the window:

 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); start = false; desktopWidget = QApplication::desktop(); m_grabber = static_cast<DesktopMouseGrabber*>(desktopWidget); // Ρ‚ΠΈΠΏ m_grabber DesktopMouseGrabber* m_grabber->main_window = static_cast<MainWindow* (this); // Ρ‚ΠΈΠΏ m_grabber->main_window - QMainWindow* m = this; connect( ui->selectButton, SIGNAL(clicked()), this, SLOT(onButtonSelectClick()) ); connect( ui->startButton, SIGNAL(clicked()), this, SLOT(onButtonStartClick ()) ); } // НаТимаСм Π½Π° ΠΊΠ½ΠΎΠΏΠΊΡƒ, сворачиваСм ΠΎΠΊΠ½ΠΎ, Π΄Π΅Π»Π°Π΅ΠΌ Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²ΠΈΠ΄ΠΆΠ΅Ρ‚ ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠ³ΠΎ ΠΎΠΊΠ½Π° Π·Π°Ρ…Π²Π°Ρ‚ΠΈΠ» ΠΌΡ‹ΡˆΡŒ void MainWindow::onButtonSelectClick() { showMinimized(); m_grabber->grabMouse(); } void MainWindow::customEvent(QEvent *e) { // ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ события ΠΊΠ»ΠΈΠΊΠ° ΠΏΠΎ ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠΌΡƒ ΠΎΠΊΠ½Ρƒ QMouseEvent* event = static_cast<QMouseEvent*>(e); m_grabber->releaseMouse(); this->show(); } } 

Problem: when you click the mouse on the desktop, nothing happens, the mouse is not released, the window does not open, what am I doing wrong?

Are there any alternative methods for solving the issue?

    2 answers 2

    Mouse and keyboard events will not get into the Qt application if they are not addressed to it. That is, the "hook" will not work. But you can alternatively. Make a screenshot of the screen:

     QPixmap pixmap = QGuiApplication::primaryScreen()->grabWindow(0); 

    Then draw it on some newly created widget stretched over the whole screen (the best method is showFullScreen() ) in the body of its overridden paintEvent() method:

     QPainter painter(this); painter.drawPixmap(rect(), pixmap, pixmap.rect()); 

    Well, then override mousePressEvent() or mouseReleaseEvent() in order to get the coordinates of the place where the user clicks, and then hide the widget itself, temporarily replacing the screen.

    • Ehm And if the video is running in the background window? - VladD
    • If the entire screen, then of course this solution does not work, because most likely there will be an ugly jump when redrawing. If for good, then it is necessary to capture the events of the system. But then it will have to write different code for each OS separately. And so, if you do not pretend to refinement and in standard cases it is a workable solution. - alexis031182
    • Well, it is not clear why primaryScreen (if I correctly understood the name of the function). And if the click will be on the second monitor? - VladD
    • QGuiApplication has a static method for getting a list of screens: screens (). Well, like about this question was not conducted. You can always correct something by the situation. - alexis031182
    • I solved this problem by parsing the input-output in linux with the mouse stream responding to the file / dev / input / mice, making a click on the screen capture. - OlegUP

    a small class of mousegrabber, in a separate thread reads / dev / input / mice (there are sometimes departures in it)

     void MouseGrabber::run() { FILE * mice; mice = fopen("/dev/input/mice", "r"); if ( !mice ) { qWarning() << "Couldn't open: /dev/input/mice"; qWarning() << "Note: You must be root user"; return ; } stop = false; char buff[3]; bool left_pressed = false; Qt::MouseButtons mb; while ( 1 ) { if (stop) break; std::fread( buff, 1, 3, mice ); if(buff[ 0 ] & 0x1 && (!buff[1] && !buff[2])) { // ΠžΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ ΠΊΠ»ΠΈΠΊΠ½ΡƒΠ»(Π½Π°ΠΆΠ°Π» ΠΈ отпустил) Π›ΠšΠœ left_pressed = true; qWarning() << QByteArray(buff).toHex() << endl; } else if (buff[0] == 0x8) { if ( !left_pressed ) continue; emit globalClick(QCursor::pos()); left_pressed = false; } else left_pressed = false; } } void MouseGrabber::onStop() { this->stop = true; } 

    MainWindow receives a globalClick () signal, reads the pixel where it was clicked, not the whole area, then what is needed is done with the received information.

     void MainWindow::onGlobalClick(QPoint pos) { mutex.lock(); // ui->label->setProperty("text", QString(" X: %1, Y: %2").arg(pos.x()).arg(pos.y())); if (!start) { px = pos.x(), py = pos.y(); } QPixmap map = QPixmap::grabWindow(this->desktopWidget->winId(), px, py, 1, 1); QImage img = map.toImage(); QRgb color = img.pixel(0, 0); parsePixel(px, py, color); mutex.unlock(); }