在函数执行期间在 PyQt5 中显示闪屏

发布于 2025-01-11 10:42:46 字数 5077 浏览 0 评论 0原文

我有一个程序,可以使用 PyQt5 显示 GUI。从我的 MainWindow 中,我打开一个 QWidget,从中启动一个函数。当此函数运行时,应该会出现 SplashScreen。该函数完成后,SplashScreen 应再次关闭。我尝试从函数内启动 SplashScreen 。但是,SplashScreen 不会出现。

我使用了以下代码:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QDialog, QProgressBar, QLabel, QFrame, QMainWindow, QVBoxLayout, QPushButton
from PyQt5.QtCore import Qt
import time

class Function:
    def loading(self):
        self.screen = SplashScreen()
        self.screen.show()
        time.sleep(10)
        self.screen.close()

class SplashScreen(QDialog):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Spash Screen Example')
        self.setFixedSize(1100, 500)
        self.setWindowFlag(Qt.FramelessWindowHint)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setWindowFlag(Qt.WindowStaysOnTopHint)
        self.initUI()

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

        self.frame = QFrame()
        layout.addWidget(self.frame)

        self.labelTitle = QLabel(self.frame)
        self.labelTitle.setObjectName('LabelTitle')

        # center labels
        self.labelTitle.resize(self.width() - 10, 150)
        self.labelTitle.move(0, 40)  # x, y
        self.labelTitle.setText('Splash Screen')
        self.labelTitle.setAlignment(Qt.AlignCenter)

        self.labelDescription = QLabel(self.frame)
        self.labelDescription.resize(self.width() - 10, 50)
        self.labelDescription.move(0, self.labelTitle.height())
        self.labelDescription.setObjectName('LabelDesc')
        self.labelDescription.setText('<strong>Working on Task #1</strong>')
        self.labelDescription.setAlignment(Qt.AlignCenter)

        self.progressBar = QProgressBar(self.frame)
        self.progressBar.resize(self.width() - 200 - 10, 50)
        self.progressBar.move(100, self.labelDescription.y() + 130)
        self.progressBar.setAlignment(Qt.AlignCenter)
        self.progressBar.setFormat('%p%')
        self.progressBar.setTextVisible(True)
        self.progressBar.setRange(0, 100)
        self.progressBar.setValue(20)

        self.labelLoading = QLabel(self.frame)
        self.labelLoading.resize(self.width() - 10, 50)
        self.labelLoading.move(0, self.progressBar.y() + 70)
        self.labelLoading.setObjectName('LabelLoading')
        self.labelLoading.setAlignment(Qt.AlignCenter)
        self.labelLoading.setText('loading...')

        self.setStyleSheet('''
                        #LabelTitle {
                            font-size: 60px;
                            color: #93deed;
                        }

                        #LabelDesc {
                            font-size: 30px;
                            color: #c2ced1;
                        }

                        #LabelLoading {
                            font-size: 30px;
                            color: #e8e8eb;
                        }

                        QFrame {
                            background-color: #2F4454;
                            color: rgb(220, 220, 220);
                        }

                        QProgressBar {
                            background-color: #DA7B93;
                            color: rgb(200, 200, 200);
                            border-style: none;
                            border-radius: 10px;
                            text-align: center;
                            font-size: 30px;
                        }

                        QProgressBar::chunk {
                            border-radius: 10px;
                            background-color: qlineargradient(spread:pad x1:0, x2:1, y1:0.511364, y2:0.523, stop:0 #1C3334, stop:1 #376E6F);
                        }
                    ''')

class Window(QWidget):
    def __init__(self):
        super().__init__()
        layout_window = QVBoxLayout()
        self.setLayout(layout_window)
        self.button = QPushButton("Open", self)
        layout_window.addWidget(self.button)
        self.button.clicked.connect(self.open)

    def open(self):
        self.function = Function()
        self.function.loading()


class MyApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.window_width, self.window_height = 1200, 800
        self.setMinimumSize(self.window_width, self.window_height)

        layout = QVBoxLayout()
        self.setLayout(layout)
        self.button = QPushButton("Open", self)
        layout.addWidget(self.button)
        self.button.clicked.connect(self.open)

    def open(self):
        self.window = Window()
        self.window.show()



if __name__ == '__main__':
    app = QApplication(sys.argv)
    myapp = MyApp()
    myapp.show()

    try:
        sys.exit(app.exec_())
    except SystemExit:
        print('Closing Window...')

我用 time.sleep 表示该函数(在原始程序中进行了一些耗时的数据处理)。当我省略 close-function 时,“SplashScreen”会在 time.sleep 完成后打开。

I have a program where I display the GUI with PyQt5. From my MainWindow I open a QWidget from which a function is started. While this function is running a SplashScreen should appear. As soon as the function is finished, the SplashScreen should close again. I have tried to start the SplashScreen from within the function. However, the SplashScreen does not appear.

I have used the following code:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QDialog, QProgressBar, QLabel, QFrame, QMainWindow, QVBoxLayout, QPushButton
from PyQt5.QtCore import Qt
import time

class Function:
    def loading(self):
        self.screen = SplashScreen()
        self.screen.show()
        time.sleep(10)
        self.screen.close()

class SplashScreen(QDialog):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Spash Screen Example')
        self.setFixedSize(1100, 500)
        self.setWindowFlag(Qt.FramelessWindowHint)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setWindowFlag(Qt.WindowStaysOnTopHint)
        self.initUI()

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

        self.frame = QFrame()
        layout.addWidget(self.frame)

        self.labelTitle = QLabel(self.frame)
        self.labelTitle.setObjectName('LabelTitle')

        # center labels
        self.labelTitle.resize(self.width() - 10, 150)
        self.labelTitle.move(0, 40)  # x, y
        self.labelTitle.setText('Splash Screen')
        self.labelTitle.setAlignment(Qt.AlignCenter)

        self.labelDescription = QLabel(self.frame)
        self.labelDescription.resize(self.width() - 10, 50)
        self.labelDescription.move(0, self.labelTitle.height())
        self.labelDescription.setObjectName('LabelDesc')
        self.labelDescription.setText('<strong>Working on Task #1</strong>')
        self.labelDescription.setAlignment(Qt.AlignCenter)

        self.progressBar = QProgressBar(self.frame)
        self.progressBar.resize(self.width() - 200 - 10, 50)
        self.progressBar.move(100, self.labelDescription.y() + 130)
        self.progressBar.setAlignment(Qt.AlignCenter)
        self.progressBar.setFormat('%p%')
        self.progressBar.setTextVisible(True)
        self.progressBar.setRange(0, 100)
        self.progressBar.setValue(20)

        self.labelLoading = QLabel(self.frame)
        self.labelLoading.resize(self.width() - 10, 50)
        self.labelLoading.move(0, self.progressBar.y() + 70)
        self.labelLoading.setObjectName('LabelLoading')
        self.labelLoading.setAlignment(Qt.AlignCenter)
        self.labelLoading.setText('loading...')

        self.setStyleSheet('''
                        #LabelTitle {
                            font-size: 60px;
                            color: #93deed;
                        }

                        #LabelDesc {
                            font-size: 30px;
                            color: #c2ced1;
                        }

                        #LabelLoading {
                            font-size: 30px;
                            color: #e8e8eb;
                        }

                        QFrame {
                            background-color: #2F4454;
                            color: rgb(220, 220, 220);
                        }

                        QProgressBar {
                            background-color: #DA7B93;
                            color: rgb(200, 200, 200);
                            border-style: none;
                            border-radius: 10px;
                            text-align: center;
                            font-size: 30px;
                        }

                        QProgressBar::chunk {
                            border-radius: 10px;
                            background-color: qlineargradient(spread:pad x1:0, x2:1, y1:0.511364, y2:0.523, stop:0 #1C3334, stop:1 #376E6F);
                        }
                    ''')

class Window(QWidget):
    def __init__(self):
        super().__init__()
        layout_window = QVBoxLayout()
        self.setLayout(layout_window)
        self.button = QPushButton("Open", self)
        layout_window.addWidget(self.button)
        self.button.clicked.connect(self.open)

    def open(self):
        self.function = Function()
        self.function.loading()


class MyApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.window_width, self.window_height = 1200, 800
        self.setMinimumSize(self.window_width, self.window_height)

        layout = QVBoxLayout()
        self.setLayout(layout)
        self.button = QPushButton("Open", self)
        layout.addWidget(self.button)
        self.button.clicked.connect(self.open)

    def open(self):
        self.window = Window()
        self.window.show()



if __name__ == '__main__':
    app = QApplication(sys.argv)
    myapp = MyApp()
    myapp.show()

    try:
        sys.exit(app.exec_())
    except SystemExit:
        print('Closing Window...')

I have represented the function (in the original program some time consuming data processing takes place) with time.sleep. When I leave out the close-function, the 'SplashScreen' opens after the time.sleep is finished.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

皓月长歌 2025-01-18 10:42:46

time.sleep 将阻止事件循环,因此任何与 GUI 相关的操作都将暂停,直到完成为止。因此,您需要使用 processEvents 显式强制处理任何待处理事件:

class Function:
    def loading(self):
        self.screen = SplashScreen()
        self.screen.show()
        for i in range(100):
            self.screen.progressBar.setValue(i)
            QApplication.processEvents()
            time.sleep(0.1)
        self.screen.close()

或者将耗时的任务移至工作线程,然后使用信号来更新 GUI:

from PyQt5.QtCore import pyqtSignal, QThread

class Thread(QThread):
    progressChanged = pyqtSignal(int)

    def run(self):
        for i in range(100):
            QThread.msleep(100)
            self.progressChanged.emit(i)

class Function:
    def loading(self):
        self.screen = SplashScreen()
        self.screen.show()
        self.thread = Thread()
        self.thread.progressChanged.connect(
            self.screen.progressBar.setValue)
        self.thread.finished.connect(self.screen.close)
        self.thread.start()

通常建议使用后一种方法,但如果任务无法分解为离散的步骤,则可能需要使用 多处理 代替。

The time.sleep will block the event-loop, so any GUI-related operations will be suspended until it finishes. You therefore need to explicitly force processing of any pending events, using processEvents:

class Function:
    def loading(self):
        self.screen = SplashScreen()
        self.screen.show()
        for i in range(100):
            self.screen.progressBar.setValue(i)
            QApplication.processEvents()
            time.sleep(0.1)
        self.screen.close()

Or move the time-consuming task to a worker thread, and then use signals to update the GUI:

from PyQt5.QtCore import pyqtSignal, QThread

class Thread(QThread):
    progressChanged = pyqtSignal(int)

    def run(self):
        for i in range(100):
            QThread.msleep(100)
            self.progressChanged.emit(i)

class Function:
    def loading(self):
        self.screen = SplashScreen()
        self.screen.show()
        self.thread = Thread()
        self.thread.progressChanged.connect(
            self.screen.progressBar.setValue)
        self.thread.finished.connect(self.screen.close)
        self.thread.start()

The latter approach is usually recommended, but if the task can't be broken up into discrete steps, you may need to use multiprocessing instead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文