【问题标题】:Getting screen pixels on mouse press在鼠标按下时获取屏幕像素
【发布时间】:2020-06-13 09:29:23
【问题描述】:

当我单击屏幕上的任意位置(包括我的应用程序外部)时,我想获取鼠标坐标处的屏幕像素。

作为第一步,我截图如下:

from PyQt5 import QtWidgets, QtGui

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        w = QtWidgets.QWidget()
        layout = QtWidgets.QVBoxLayout()
        w.setLayout(layout)
        self.setCentralWidget(w)

        screenshot = QtWidgets.QApplication.primaryScreen().grabWindow(w.winId())

如何将我点击的坐标映射到屏幕截图?

我认为下一步是将屏幕截图转换为Pixmap 以提取像素,但我不知道如何将其与鼠标按下坐标联系起来。

【问题讨论】:

    标签: python python-3.x pyqt5 pyside2


    【解决方案1】:

    在任何 Qt 窗口外部捕获点击事件的唯一方法是通过grabMouse()。考虑到这仅适用于 Linux:

    注意:在 Windows 上,grabMouse() 仅在鼠标位于进程拥有的窗口内时才有效。在 macOS 上,grabMouse() 仅在鼠标位于该小部件的框架内时才有效。

    还要注意抓鼠标可能很危险:

    警告:鼠标抓取应用程序中的错误经常锁定终端。使用此函数时要格外小心,并考虑在调试时使用 -nograb 命令行选项。

    只要小部件抓住鼠标,它就会捕获所有个鼠标事件(包括鼠标滚轮),无论它们的位置如何,所以它也非常重要尽快释放它。然后,就不需要映射坐标了:mousePressEvent 已经提供了基于屏幕坐标的全局位置,并且由于您已经截取了整个屏幕区域,因此这些坐标将匹配。

    最后,要获取像素数据,将grabWindow提供的QPixmap转换成QImage并使用pixelColor

    由于grabMouse 的平台限制,在以下示例中,我将创建一个透明窗口,充当“假”鼠标抓取器。

    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self):
            super(MainWindow, self).__init__()
    
            w = QtWidgets.QWidget()
            layout = QtWidgets.QVBoxLayout()
            w.setLayout(layout)
            self.setCentralWidget(w)
            self.grabButton = QtWidgets.QPushButton('Grab')
            layout.addWidget(self.grabButton)
            self.label = QtWidgets.QLabel('Waiting')
            layout.addWidget(self.label)
            self.grabButton.setCheckable(True)
            self.grabButton.toggled.connect(self.startGrab)
    
            self.desktopId = QtWidgets.QApplication.desktop().winId()
    
            if sys.platform != 'linux':
                self.grabber = QtWidgets.QWidget(flags=QtCore.Qt.FramelessWindowHint)
                self.grabber.setAttribute(QtCore.Qt.WA_TranslucentBackground)
                self.grabber.installEventFilter(self)
            else:
                self.grabber = None
    
        def grabPixel(self, event):
            buttonRect = self.grabButton.rect()
            buttonRect.translate(self.grabButton.mapToGlobal(QtCore.QPoint()))
            if event.globalPos() not in buttonRect:
                screenshot = QtWidgets.QApplication.primaryScreen().grabWindow(self.desktopId).toImage()
                pixel = screenshot.pixelColor(event.globalPos())
                self.label.setText('Click on {}x{}\nRGB: {}'.format(event.globalX(), event.globalY(), pixel.name()))
            self.grabButton.toggle()
    
        def startGrab(self, grab):
            if grab:
                if self.grabber:
                    rect = QtCore.QRect()
                    for screen in QtWidgets.QApplication.screens():
                        rect |= screen.geometry()
                    self.grabber.setGeometry(rect)
                    self.grabber.show()
                else:
                    self.grabMouse()
            else:
                self.releaseMouse()
    
        def eventFilter(self, source, event):
            if source == self.grabber and event.type() == QtCore.QEvent.MouseButtonPress:
                self.grabPixel(event)
                self.grabber.hide()
            return super().eventFilter(source, event)
    
        def mousePressEvent(self, event):
            self.grabPixel(event)
    

    【讨论】:

    猜你喜欢
    • 2011-08-15
    • 2021-01-05
    • 1970-01-01
    • 1970-01-01
    • 2022-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多