在函数执行期间在 PyQt5 中显示闪屏
我有一个程序,可以使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
time.sleep 将阻止事件循环,因此任何与 GUI 相关的操作都将暂停,直到完成为止。因此,您需要使用 processEvents 显式强制处理任何待处理事件:
或者将耗时的任务移至工作线程,然后使用信号来更新 GUI:
通常建议使用后一种方法,但如果任务无法分解为离散的步骤,则可能需要使用 多处理 代替。
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:Or move the time-consuming task to a worker thread, and then use signals to update the GUI:
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.