SuperStew
SuperStew

Reputation: 3054

PyQt5 Grab and save section of screen

So the idea is that I should be able to fire up the script, select a portion of the screen, then hit enter (or otherwise trigger it) to save the selection.

I've got a good bit of the code from other posts and things, but now I'm stuck. I can select any portion of the screen and resize as needed, but I can't seem to get it to recognize the "enter" key. Right now the "keyPressEvent" function is just supposed to print a message so I know it worked, but I got nothing. Any ideas?

import sys
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import Qt, QPoint, QRect, QSize
from PyQt5.QtGui import QScreen
from PyQt5.QtWidgets import QApplication, QLabel, QRubberBand


class MyLabel(QtWidgets.QLabel):

    def __init__(self, parent=None):
        QtWidgets.QLabel.__init__(self, parent)
        self.selection = QtWidgets.QRubberBand(QtWidgets.QRubberBand.Rectangle, self)


    def keyPressEvent(self, qKeyEvent):
        print(qKeyEvent.key())
        if qKeyEvent.key() == QtCore.Qt.Key_Return: 
            print('Enter pressed')
        else:
            super().keyPressEvent(qKeyEvent)

    def mousePressEvent(self, event):
        '''
            Mouse is pressed. If selection is visible either set dragging mode (if close to border) or hide selection.
            If selection is not visible make it visible and start at this point.
        '''

        if event.button() == QtCore.Qt.LeftButton:

            position = QtCore.QPoint(event.pos())
            if self.selection.isVisible():
                # visible selection
                if (self.upper_left - position).manhattanLength() < 20:
                    # close to upper left corner, drag it
                    self.mode = "drag_upper_left"
                elif (self.lower_right - position).manhattanLength() < 20:
                    # close to lower right corner, drag it
                    self.mode = "drag_lower_right"
                else:
                    # clicked somewhere else, hide selection
                    self.selection.hide()
            else:
                # no visible selection, start new selection
                self.upper_left = position
                self.lower_right = position
                self.mode = "drag_lower_right"
                self.selection.show()

    def mouseMoveEvent(self, event):
        '''
            Mouse moved. If selection is visible, drag it according to drag mode.
        '''

        if self.selection.isVisible():
            # visible selection
            if self.mode is "drag_lower_right":
                self.lower_right = QtCore.QPoint(event.pos())
            elif self.mode is "drag_upper_left":
                self.upper_left = QtCore.QPoint(event.pos())
            # update geometry
            self.selection.setGeometry(QtCore.QRect(self.upper_left, self.lower_right).normalized())


class mainUI(QtWidgets.QWidget):

    def __init__(self):
        super(mainUI, self).__init__()
        self.initUI()

    def initUI(self):
        layout = QtWidgets.QVBoxLayout(self)

        label = MyLabel(self)
        pixmap = QScreen.grabWindow(app.primaryScreen(), app.desktop().winId())
        label.setPixmap(pixmap)
        layout.addWidget(label)

        self.setLayout(layout)

        geometry = app.desktop().availableGeometry()

        self.setFixedSize(geometry.width(), geometry.height())

        # self.setWindowFlags( self.windowFlags() | Qt.FramelessWindowHint)
        self.show()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    window = mainUI()

    sys.exit(app.exec_())

EDIT

Alright this code works, although to be honest I'm not 100% sure why.

import sys
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import Qt, QPoint, QRect, QSize
from PyQt5.QtGui import QScreen
from PyQt5.QtWidgets import QApplication, QLabel, QRubberBand, QAction

class KpeWindow(QtWidgets.QLabel):
    def __init__(self, parent=None):
        QtWidgets.QLabel.__init__(self,parent)
        main = QtWidgets.QVBoxLayout(self)
        self.selection = QtWidgets.QRubberBand(QtWidgets.QRubberBand.Rectangle, self)

        # label = QLabel(self)
        # label.setText('Test the keyPressEvent')
        # main.addWidget(label)

        # self.adjustSize()
        # self.setLayout(main)

    def keyPressEvent(self, event):
        print(event.key())
        if event.key() == QtCore.Qt.Key_Return:
            print('yay')

        #QtWidgets.QMessageBox.warning(self, 'MDI', 'keyPressEvent')
        self.parent().keyPressEvent(event)


    def mousePressEvent(self, event):
        '''
            Mouse is pressed. If selection is visible either set dragging mode (if close to border) or hide selection.
            If selection is not visible make it visible and start at this point.
        '''
        print(event)
        if event.button() == QtCore.Qt.LeftButton:

            position = QtCore.QPoint(event.pos())
            if self.selection.isVisible():
                # visible selection
                if (self.upper_left - position).manhattanLength() < 20:
                    # close to upper left corner, drag it
                    self.mode = "drag_upper_left"
                elif (self.lower_right - position).manhattanLength() < 20:
                    # close to lower right corner, drag it
                    self.mode = "drag_lower_right"
                else:
                    # clicked somewhere else, hide selection
                    self.selection.hide()
            else:
                # no visible selection, start new selection
                self.upper_left = position
                self.lower_right = position
                self.mode = "drag_lower_right"
                self.selection.show()

    def mouseMoveEvent(self, event):
        '''
            Mouse moved. If selection is visible, drag it according to drag mode.
        '''

        if self.selection.isVisible():
            # visible selection
            if self.mode is "drag_lower_right":
                self.lower_right = QtCore.QPoint(event.pos())
            elif self.mode is "drag_upper_left":
                self.upper_left = QtCore.QPoint(event.pos())
            # update geometry
            self.selection.setGeometry(QtCore.QRect(self.upper_left, self.lower_right).normalized())

class MainWindow(QtWidgets.QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()
        QtWidgets.QMainWindow.__init__(self)
        #self.setWindowTitle('KeyPressEvent Test')
        # main = QtWidgets.QVBoxLayout(self)
        # child = KpeWindow(self)
        # child.setFocusPolicy(Qt.StrongFocus)
        # self.setFocusProxy(child)
        # main.addWidget(child)
        # child.setFocus(True)

        layout = QtWidgets.QVBoxLayout(self)

        label = KpeWindow(self)
        pixmap = QScreen.grabWindow(app.primaryScreen(), app.desktop().winId())
        label.setPixmap(pixmap)
        layout.addWidget(label)
        #new
        label.setFocusPolicy(Qt.StrongFocus)
        self.setFocusProxy(label)
        label.setFocus(True)

        self.setLayout(layout)

        geometry = app.desktop().availableGeometry()

        self.setFixedSize(geometry.width(), geometry.height())


        # self.setWindowFlags( self.windowFlags() | Qt.FramelessWindowHint)
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainWin = MainWindow()
    mainWin.show()
    sys.exit(app.exec_())

Upvotes: 1

Views: 2953

Answers (1)

ekhumoro
ekhumoro

Reputation: 120598

You need to set the focus policy on the label to get keyboard events:

class MyLabel(QtWidgets.QLabel):

    def __init__(self, parent=None):
        ...
        self.setFocusPolicy(Qt.TabFocus)

Upvotes: 1

Related Questions