time.sleep() 和背景 Windows PyQt5

2022-01-12 00:00:00 python pyqt pyqt5 sleep

问题描述


鉴于此,我从 PyQt5 模块开始,我仍然在慢慢理解它背后的逻辑.也就是说,我遇到了一个无法找到答案的问题,希望您能帮助我.
我有这个脚本:


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_())

在网上搜索,发现问题与time.sleep(2)"有关,即指令阻塞了两秒后才出现的窗口.
事实是,我想花一两秒钟,显示完成栏,然后再重置并继续执行def run (self)"中包含的下一条语句.
那么,有没有办法在不使用 Time 模块的情况下暂停?我不知道,也许用QTimer?我再说一遍,我对 PyQt5 还不太了解,所以我不知道 QTimer 是否可以做同样的事情.
如果 QTimer 做不到,是否可以通过其他方式实现?我想避免使用 PyQt5 的线程",因为我读到有可能做到这一点,但我想避免仅将它用于 Timer 模块.


我只添加了一个问题,以避免打开另一个问题并发布相同的脚本.
在脚本中,窗口背景是通过 "oImage = QImage (" bgloading.png ")" 等完成的.
但是,我注意到,如果发现文件名错误,或者文件本身丢失,则背景为黑色.因此,如果有任何错误(名称错误或文件丢失),是否可以设置背景,例如白色?
因为当窗口加载此错误"时,不会引发异常,脚本会继续执行.



我编辑了已发布的脚本,使其仅包含 PyQt5 部分,因此您可以尝试一下.显然只有图片丢失了,可以用任意图片替换.
不幸的是我忘记写报告self.set_display()"的部分是表明一旦PyQt5执行的工作被终止,它将被关闭(仍然丢失,因为使用Pycharm我会关闭执行程序中的脚本).脚本将通过调用self.set_display()"函数继续.

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.



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:按照建议,我尝试替换time.sleep (2)",但得到了相同的结果.问题是,如果我不暂停,窗口会正常显示,但重置发生得太快,用户看不到进度条的填充.如果我改为输入time.sleep (2)",或者建议的解决方案,窗口仅在暂停后出现,即重置已经发生.

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.


解决方案

对PyQt友好的等价于time.sleep(2)的表达式如下:

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

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

<小时>

问题是因为你在暂停后显示小部件,你必须在调用run()之前做,另外一个错误是使用QImage,因为您必须使用 QPixmap 的小部件问题.


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.

如果文件不存在,那么 QPixmap 将为空,要知道它是否存在,您应该使用 isNull() 方法:

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("...")

相关文章