2

I want to upgrade or convert this code from pyqt4 to pyqt5 as this code is not compatible with latest pyqt5.

So can someone tell me what major changes i can make in this code to run it in pyqt5.

import sys
from PyQt4.QtCore import Qt
from PyQt4.QtCore import QRectF
from PyQt4.QtWidgets import QApplication
from PyQt4.QtGui import QColor
from PyQt4.QtGui import QFont
from PyQt4.QtGui import QPainter
from PyQt4.QtGui import QPixmap
from PyQt4.QtGui import QTextOption
from PyQt4.QtGui import QToolTip
from PyQt4.QtGui import QWidget

this are all the imported libraries for this code

class AreaSelector(QWidget):

    def __init__(self, parent=None):

        QWidget.__init__(self, None, Qt.FramelessWindowHint)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setWindowState(Qt.WindowFullScreen)
        self.setAutoFillBackground(False)

        self.parent = parent
        self.start_x = 0
        self.start_y = 0
        self.end_x = 0
        self.end_y = 0
        self.current_x = 0
        self.current_y = 0

    def showEvent(self, event):

        self.bg = QPixmap.grabWindow(QApplication.desktop().winId())
        self.screen_geometry = QApplication.desktop().screenGeometry(self)

    def mousePressEvent(self, event):

        self.start_x = event.globalX()
        self.start_y = event.globalY()

    def mouseReleaseEvent(self, event):

        self.end_x = event.globalX()
        self.end_y = event.globalY()

please view the full code here full code

1 Answer 1

1

Translating a PyQt4 code to PyQt5 is not a trivial task:

  • PyQt4 and PyQt5 are wrappers of Qt4 and Qt5, respectively, so both are affected by the changes of that transition, and one of the transitions is that the QtGui sub-module of Qt4 was divided into the QtGui and QtWidgets sub-modules of Qt5.
  • Some classes and methods are deprecated so you will have to find an equivalent if it exists.

In this case both things happen, the solution for the first case is simple: You must look in the Qt docs and check to which sub-module it belongs, for example QToolTip, at the top there is a table:

enter image description here

And the part of QT += widgets that indicates that it belongs to the QtWidgets sub-module is observed.

But the second case is somewhat more complicated since it involves looking for an equivalent that may or may not be in the same class, in this case it happens with the QPixmap.grabWindow() method which is deprecates (see here for more information). After doing a search you can replace that code with QApplication.primaryScreen().grabWindow(0).

Considering all of the above, the translation is:

import sys
from PyQt5.QtCore import QRectF, Qt
from PyQt5.QtGui import QColor, QFont, QPainter, QPixmap, QTextOption, QScreen
from PyQt5.QtWidgets import QApplication, QToolTip, QWidget


class AreaSelector(QWidget):
    def __init__(self, parent=None):

        QWidget.__init__(self, None, Qt.FramelessWindowHint)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setWindowState(Qt.WindowFullScreen)
        self.setAutoFillBackground(False)

        self.parent = parent
        self.start_x = 0
        self.start_y = 0
        self.end_x = 0
        self.end_y = 0
        self.current_x = 0
        self.current_y = 0

    def showEvent(self, event):
        self.bg = QApplication.primaryScreen().grabWindow(0)
        self.screen_geometry = QApplication.primaryScreen().geometry()

    def mousePressEvent(self, event):

        self.start_x = event.globalX()
        self.start_y = event.globalY()

    def mouseReleaseEvent(self, event):

        self.end_x = event.globalX()
        self.end_y = event.globalY()

    def mouseMoveEvent(self, event):

        self.current_x = event.globalX()
        self.current_y = event.globalY()
        self.repaint()

        text = "Start: %sx%s \nEnd: %sx%s" % (
            self.start_x,
            self.start_y,
            self.current_x,
            self.current_y,
        )
        QToolTip.showText(event.pos(), text)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Return:
            self._acceptSelection()
        elif event.key() == Qt.Key_Escape:
            self.close()

    def _acceptSelection(self):

        if self.parent is not None:
            self.parent.areaSelectEvent(
                self.start_x, self.start_y, self.end_x, self.end_y
            )
        self.close()

    def paintEvent(self, event):

        painter = QPainter()
        painter.begin(self)

        painter.fillRect(self.screen_geometry, QColor(10, 10, 10, 125))

        self._paint_selection(painter)
        self._paint_usage_text(painter)
        painter.end()

    def _paint_usage_text(self, painter):

        font = QFont("Helvetica [Cronyx]", 26, QFont.Bold)
        painter.setFont(font)
        painter.setPen(QColor(255, 255, 255, 255))

        screen_width = self.screen_geometry.width()
        text_width = 800
        text_start_x = screen_width / 2 - text_width / 2

        screen_height = self.screen_geometry.height()
        text_height = 200
        text_start_y = screen_height / 2 - text_height / 2

        textoption = QTextOption(Qt.AlignCenter)
        textbox = QRectF(text_start_x, text_start_y, text_width, text_height)
        painter.drawText(
            textbox,
            "Click & Drag to select an area\n" "ENTER to confirm or ESC to cancel",
            textoption,
        )
        painter.drawRoundedRect(textbox, 20, 20)

    def _paint_selection(self, painter):
        """Draws the current user selection"""
        rectangle = QRectF()

        if self.start_x > self.current_x:
            rectangle.setLeft(self.current_x)
            rectangle.setRight(self.start_x)

        else:
            rectangle.setLeft(self.start_x)
            rectangle.setRight(self.current_x)

        if self.start_y > self.current_y:
            rectangle.setTop(self.current_y)
            rectangle.setBottom(self.start_y)

        else:
            rectangle.setTop(self.start_y)
            rectangle.setBottom(self.current_y)

        painter.drawPixmap(rectangle, self.bg, rectangle)
        painter.drawRect(rectangle)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = AreaSelector()
    main.show()
    sys.exit(app.exec_())
Sign up to request clarification or add additional context in comments.

4 Comments

this solution works but can you translate this into (TKINTER) gui code.
@amit9867 I don't know, I only dedicate myself to PyQt. Each library manages its own logic.
@amit9867 Do not ask to translate a code from one library to another, in this particular case it is an upgrade (pyqt4-> pyqt5) so it is valid, but if you want to do it between libraries your question would be too wide so it could be closed.
I got it tkinter is different from pyqt5 but can you tell me how can i get the coordinates of that box created by the user and use it in an another script as a input.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.