ianzhao05 / textshot

Python tool for grabbing text via screenshot
MIT License
1.72k stars 258 forks source link

Failed when have multiple monitors #19

Open KeyWgh opened 4 years ago

KeyWgh commented 4 years ago
image

Once I unplugged from external monitors it worked well. The problem is raised from line 29 in textshot.py, self.screen = QtWidgets.QApplication.screenAt(QtGui.QCursor.pos()).grabWindow(0)

My system is MacOS 10.15.3, with python 3.6.9. Thank you.

ianzhao05 commented 4 years ago

I do not currently have the means to reproduce this, but I will try to fix it when I can. Seems strange, like an internal Qt error.

hasantahir commented 3 years ago

Also on multiple monitors, I am facing this behaviour where the text is selected from the other monitor. After adding pil_img.show() after line 84 in textshot.py, the scanned image spans across the two monitors. I am on macOS 11.3.1, python 3.8.5 and tesseract 4.1.1. The other packages were installed as per the requirements.txt.

As seen in the captured image, the scanned text comes from a PDF open on the second monitor.

Kapture 2021-05-05 at 15 34 38

Although this goes against the guidelines of a dark background and white text, I must also mention here that the app works fine when the Mirror Displays option is checked in the OS settings. Here are the generated images obtained through pil_img.show() used on the Preview tab in this window:

image Mirrored Display ON

image Mirrored Display OFF

ianzhao05 commented 3 years ago

Thank you for the detailed information. In general, working with multiple monitors and grabbing the correct region is quite finicky. I believe it is OS dependent, and I don't currently have the setup to test/debug this.

StefRe commented 2 years ago

To make it work for my dual monitor setup on Windows 10 (PyQt version 5.12.3), I had to set the geometry for the whole desktop (two screens side by side from left to right) instead of setting the window to fullscreen:

@@ -23,9 +21,10 @@ class Snipper(QtWidgets.QWidget):
         self.setWindowFlags(
             Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Dialog
         )
-        self.setWindowState(self.windowState() | Qt.WindowFullScreen)
-
-        self.screen = QtWidgets.QApplication.screenAt(QtGui.QCursor.pos()).grabWindow(0)
+        desktop_geometry = QtWidgets.QApplication.desktop().geometry()
+        self.setGeometry(desktop_geometry)
+        self.screen = QtWidgets.QApplication.screens()[0].grabWindow(
+            0, *desktop_geometry.getRect())
         palette = QtGui.QPalette()
         palette.setBrush(self.backgroundRole(), QtGui.QBrush(self.screen))
         self.setPalette(palette)
jatolentino commented 4 months ago

@StefRe I also made it work with two monitors (top & bottom)

class Snipper(QtWidgets.QWidget):
    def __init__(self, parent, langs=None, flags=Qt.WindowFlags()):
        super().__init__(parent=parent, flags=flags)

        self.setWindowTitle("TextShot")
        self.setWindowFlags(
            Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Dialog
        )
        #self.setWindowState(self.windowState() | Qt.WindowFullScreen)

        #self._screen = QtWidgets.QApplication.screenAt(QtGui.QCursor.pos())

        desktop_geometry = QtWidgets.QApplication.desktop().geometry()
        self.setGeometry(desktop_geometry)
        self.screen = QtWidgets.QApplication.screens()[0].grabWindow(0, *desktop_geometry.getRect())

        palette = QtGui.QPalette()
        #palette.setBrush(self.backgroundRole(), QtGui.QBrush(self.getWindow()))
        palette.setBrush(self.backgroundRole(), QtGui.QBrush(self.screen))
        self.setPalette(palette)

        QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.CrossCursor))

        self.start, self.end = QtCore.QPoint(), QtCore.QPoint()
        self.langs = langs

    def getWindow(self):
        #return self._screen.grabWindow(0)
        desktop_geometry = QtWidgets.QApplication.desktop().geometry()
        return QtWidgets.QApplication.screens()[0].grabWindow(0, *desktop_geometry.getRect())