Search code examples
pythonpyqtpyqt4qlabel

Pixmap image size in Qlabel


I'm trying to get an image to fit my label entirely without using setScaledContents(True) since I'd like my ImageGrab to have the exact same dimensions as the QLabel space.

I use a PIL ImageGrab with a bbox. if I chance the parameters to a wider width and higher height it will crash the program without any errors. I have attached a picture where the Image in the Label is localed left center. I'd like it to the top left. So that it can expand down and to the right if I increased the size.

But I am curious as to why I am unable to increase the size of the bbox. (0, 0, 400, 220) works fine but (0, 0, 420, 220) will not upload the Image and closes down the GUI without any errors.

I'd like to have a ImageGrab with bbox (0, 0, 800, 700) and a QLabel with size(800, 700) so it can fit it perfectly.

class Main(QMainWindow):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.setGeometry(200, 200, 1000, 700)
        self.setWindowTitle('threads')

        self.mainFrame = QFrame(self)
        self.mainFrame.resize(1000, 650)
        self.mainFrame.move(0, 50)
        self.mainFrame.setStyleSheet("background-color: rbg(50, 50, 50)")

        self.testButton = QPushButton("Click", self)
        self.testButton.resize(500,30)
        self.connect(self.testButton, SIGNAL("clicked()"), self.Capture)    

        self.label_ = QLabel(self.mainFrame)
        self.label_.move(10, 10)
        self.label_.resize(980, 630)
        self.label_.setStyleSheet("background-color: rbg(150, 150, 150)")

    @pyqtSlot(QImage) 
    def ChangeFrame(self, image):  

        pixmap = QPixmap.fromImage(image)           
        self.label_.setPixmap(pixmap)

    def Capture(self):       
        self.thread_ = CaptureScreen()        
        self.connect(self.thread_, SIGNAL("ChangeFrame(QImage)"), self.ChangeFrame, Qt.QueuedConnection)
        self.thread_.start()     


class CaptureScreen(QThread):
    pixmap = pyqtSignal(QImage)

    def __init__(self, parent = None):
        QThread.__init__(self)

    def __del__(self):
        print("?????")
        self.exiting = True
        self.wait()

    def run(self):         
        while(True):
            time.sleep(1/60)

            img = ImageGrab.grab(bbox=(0, 0, 420, 220))

            frame = ImageQt(img)
            frame = QImage(frame)

            self.emit( SIGNAL("ChangeFrame(QImage)"), frame)

enter image description here


Solution

  • The solution is to use layouts, and set the alignment in QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft.

    I also recommend using the new connection syntax, on the other hand if you are going to inherit from QMainWindow in the constructor you must call it. And finally when you use QMainWindow you must set a central widget.

    import time
    from PyQt4 import QtCore, QtGui
    from PIL import ImageGrab, ImageQt
    
    
    class Main(QtGui.QMainWindow):
        def __init__(self, parent=None):
            QtGui.QMainWindow.__init__(self, parent)
    
            self.setGeometry(200, 200, 1000, 700)
            self.setWindowTitle('threads')
    
            main_widget = QtGui.QWidget()
            self.setCentralWidget(main_widget)
    
            lay = QtGui.QVBoxLayout(main_widget)
            self.testButton = QtGui.QPushButton("Click")
            self.testButton.setFixedHeight(30)
            self.testButton.clicked.connect(self.capture)
    
            mainFrame = QtGui.QFrame()
            mainFrame.setStyleSheet("background-color: rbg(50, 50, 50)")
    
            _lay = QtGui.QVBoxLayout(mainFrame)
            _lay.setContentsMargins(0, 0, 0, 0)
            self.label_ = QtGui.QLabel()
            _lay.addWidget(self.label_, 0, QtCore.Qt.AlignTop|QtCore.Qt.AlignLeft)
    
            lay.addWidget(self.testButton)
            lay.addWidget(mainFrame)
    
        @QtCore.pyqtSlot(QtGui.QImage) 
        def changeFrame(self, image):  
            pixmap = QtGui.QPixmap.fromImage(image)           
            self.label_.setPixmap(pixmap)
    
        @QtCore.pyqtSlot() 
        def capture(self):       
            self.thread_ = CaptureScreen()       
            self.thread_.changedFrame.connect(self.changeFrame, QtCore.Qt.QueuedConnection)
            self.thread_.start()     
            self.testButton.setDisabled(True)
    
    
    class CaptureScreen(QtCore.QThread):
        changedFrame = QtCore.pyqtSignal(QtGui.QImage)
    
        def __del__(self):
            print("?????")
            self.exiting = True
            self.quit()
            self.wait()
    
        def run(self):         
            while True:
                time.sleep(1/60)
                w, h = 420, 220
                img = ImageGrab.grab(bbox=(0, 0, w, h))
                frame = ImageQt.toqimage(img)
                self.changedFrame.emit(QtGui.QImage(frame))
    
    
    if __name__ == '__main__':
        import sys
        app = QtGui.QApplication(sys.argv)
        w = Main()
        w.show()
        sys.exit(app.exec_())