2
votes


given that, I'm starting with the PyQt5 module, I'm still slowly understanding the logic behind it. That said, I'm having a problem that I can not find an answer to and I hope you can help me.
I have this script:

import sys, socket, time
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from io import BytesIO as by

class loadGame(QWidget):
    wLoadDisplay = 768
    hLoadDisplay = 576
    wLoadBar = 650
    hLoadBar = 40

    pbarCSS = """
    QProgressBar
    {
        font-size: 20px;
        font-weight: bold;
        background-color: #FFF;
        border: 4px solid #000;
        text-align: center;
    }
    QProgressBar::chunk
    {
        background-color: #FF0000;
        width: 1px;
    }
    """

    labelCSS = """
    QLabel
    {
        font-size: 20px;
        font-weight: bold;
        background-color: #FFF;
        border: 4px solid #000;
    }
    """

    fileResource = []
    imgResource = []
    vidResource = []
    audResource = []
    diaResource = []
    txtResource = []

    internetConnection = False

    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)

        self.outputFile = by()

        self.pbar = QProgressBar(self)
        self.pbar.setGeometry((self.wLoadDisplay / 2 - self.wLoadBar / 2), (self.hLoadDisplay / 2 - self.hLoadBar * 2),
                              self.wLoadBar, self.hLoadBar)
        self.pbar.setFormat("%v/%m")
        self.pbar.setValue(0)
        self.pbar.setStyleSheet(self.pbarCSS)

        self.label = QLabel(self)
        self.label.setGeometry((self.wLoadDisplay / 2 - self.wLoadBar / 2), (self.hLoadDisplay / 2),
                               self.wLoadBar, self.hLoadBar)
        self.label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
        self.label.setStyleSheet(self.labelCSS)

        self.setGeometry(0, 0, self.wLoadDisplay, self.hLoadDisplay)
        oImage = QImage("bgloading.png")
        sImage = oImage.scaled(QSize(self.wLoadDisplay, self.hLoadDisplay))
        palette = QPalette()
        palette.setBrush(10, QBrush(sImage))
        self.setPalette(palette)

        qtRectangle = self.frameGeometry()
        centerPoint = QDesktopWidget().availableGeometry().center()
        qtRectangle.moveCenter(centerPoint)
        self.move(qtRectangle.topLeft())

        self.run()

    def run(self):
        self.checkConnection()
        if self.internetConnection:
            self.checkUpdate()
        else:
            pass

    def checkConnection(self):
        self.objectChange("Check Internet Connection", 1)
        try:
            host = socket.gethostbyname("www.google.it")
            s = socket.create_connection((host, 80), 2)
            self.internetConnection = True
        except:
            pass

        self.count()
        self.reset()

    def checkUpdate(self):
        pass

    def objectChange(self, object, n):
        self.label.setText(object)
        self.pbar.setMaximum(n)

    def count(self):
        self.pbar.setValue(self.pbar.value() + 1)

    def reset(self):
        time.sleep(2)
        self.pbar.setMaximum(0)
        self.pbar.setValue(0)
        self.label.setText("...")

if __name__ == '__main__':
    loadDisplay = QApplication(sys.argv)
    load = loadGame()
    load.show()
    sys.exit(loadDisplay.exec_())

Searching on the web, I discovered that the problem is related to "time.sleep (2)", that is, the instruction blocks the window that does not appear until two seconds have passed.
The fact is that I would like to spend one or two seconds, showing the completion of the bar, before resetting and move on to the next statement contained in "def run (self)".
So, is there a way to make that pause, without using the Time module? I do not know, maybe with QTimer? I repeat, I do not know much about PyQt5 yet, so I'm not aware if QTimer can do the same thing.
If QTimer can not do it, is it possible in any other way? I would like to avoid the "threads" of PyQt5, because I read that it would be possible to do it, but I would like to avoid using it only for the Timer module.


I only add one more question, to avoid opening another one and publishing the same script.
In the script, the window background is done via "oImage = QImage (" bgloading.png ")" etc.
I noticed, however, that if the file name were found to be wrong, or the file itself is missing, the background is colored black. So, if there are any errors (wrong name or missing file) it's possible set a background, for example, white?
Because when the window is loaded with "this error", no exception is raised and the script continues.



Edit: I've edited the published script so that it contains only the PyQt5 part, so you can try it out. Obviously only the image is missing, which can be replaced with any image.
Unfortunately I had forgotten to write that the part where "self.set_display ()" was reported was to show that once the work performed by PyQt5 was terminated, it would be closed (which was still missing, because using Pycharm I would close the execution of the script from the program). The script would continue by calling the "self.set_display ()" function.

Edit2: I tried, as suggested, to replace "time.sleep (2)", but I get the same result. The problem is that if I do not put the pause, the window appears normally, but the reset happens too quickly and the user does not see the filling of the progress bar. If instead I put "time.sleep (2)" or, the suggested solution, the window appears only after the pause, that is when the reset has already occurred.

1
Do not combine libraries, it is immaterial to make such software. - eyllanesc
PyQt5 uses it at the beginning of the script only to load the file "in memory", then it is closed and continues with Pygame. There is no combination or nothing, but it is as if they were separate. - BlackFenix06
OK, you could show a code that can run to see what is the best option, yours is not currently. - eyllanesc

1 Answers

7
votes

An expression equivalent to time.sleep(2) that is friendly to PyQt is as follows:

loop = QEventLoop()
QTimer.singleShot(2000, loop.quit)
loop.exec_()

The problem is caused because you are showing the widget after the pause, you must do it before calling run(), Also another error is to use QImage, for questions of widgets you must use QPixmap.

If the file does not exist then QPixmap will be null and to know if it is you should use the isNull() method:

    [...]

    self.setGeometry(0, 0, self.wLoadDisplay, self.hLoadDisplay)
    palette = self.palette()
    pixmap = QPixmap("bgloading.png")
    if not pixmap.isNull():
        pixmap = pixmap.scaled(QSize(self.wLoadDisplay, self.hLoadDisplay))
        palette.setBrush(QPalette.Window, QBrush(pixmap))
    else:
        palette.setBrush(QPalette.Window, QBrush(Qt.white))
    self.setPalette(palette)

    qtRectangle = self.frameGeometry()
    centerPoint = QDesktopWidget().availableGeometry().center()
    qtRectangle.moveCenter(centerPoint)
    self.move(qtRectangle.topLeft())
    self.show()

    self.run()

[...]

def reset(self):
    loop = QEventLoop()
    QTimer.singleShot(2000, loop.quit)
    loop.exec_()
    self.pbar.setMaximum(0)
    self.pbar.setValue(0)
    self.label.setText("...")