我有一个简单的应用程序,它运行一个可以持续几分钟才能完成的进程。我试图向用户提供它正在处理请求的指示 - 例如将光标更改为沙漏。
但我不能让它正常工作。我所有的尝试都导致错误或无效。而且我似乎错误地调用了光标形状,因为PyQt4.Qt.WaitCursor
返回模块不包含它的错误。
向用户指示进程正在运行的正确方法是什么?
我有一个简单的应用程序,它运行一个可以持续几分钟才能完成的进程。我试图向用户提供它正在处理请求的指示 - 例如将光标更改为沙漏。
但我不能让它正常工作。我所有的尝试都导致错误或无效。而且我似乎错误地调用了光标形状,因为PyQt4.Qt.WaitCursor
返回模块不包含它的错误。
向用户指示进程正在运行的正确方法是什么?
我认为QApplication.setOverrideCursor是您正在寻找的:
PyQt5:
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication
...
QApplication.setOverrideCursor(Qt.WaitCursor)
# do lengthy process
QApplication.restoreOverrideCursor()
PyQt4:
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QApplication
...
QApplication.setOverrideCursor(Qt.WaitCursor)
# do lengthy process
QApplication.restoreOverrideCursor()
虽然 Cameron 和 David 的答案非常适合在整个函数上设置等待光标,但我发现上下文管理器最适合为代码片段设置等待光标:
from contextlib import contextmanager
from PyQt4 import QtCore
from PyQt4.QtGui import QApplication, QCursor
@contextmanager
def wait_cursor():
try:
QApplication.setOverrideCursor(QCursor(QtCore.Qt.WaitCursor))
yield
finally:
QApplication.restoreOverrideCursor()
然后将冗长的流程代码放入 with 块中:
with wait_cursor():
# do lengthy process
pass
ekhumoro 的解决方案是正确的。此解决方案是为了风格而进行的修改。我使用了 ekhumor 所做的,但使用了 python 装饰器。
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QApplication, QCursor, QMainWidget
def waiting_effects(function):
def new_function(self):
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
try:
function(self)
except Exception as e:
raise e
print("Error {}".format(e.args[0]))
finally:
QApplication.restoreOverrideCursor()
return new_function
我可以将装饰器放在我希望微调器处于活动状态的任何方法上。
class MyWigdet(QMainWidget):
# ...
@waiting_effects
def doLengthyProcess(self):
# do lengthy process
pass
这样更好:
def waiting_effects(function):
def new_function(*args, **kwargs):
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
try:
return function(*args, **kwargs)
except Exception as e:
raise e
print("Error {}".format(e.args[0]))
finally:
QApplication.restoreOverrideCursor()
return new_function
根据我的说法,添加光标的最佳方法是使用装饰器。通过这种方式,您只需将光标添加到该函数作为装饰器即可运行任何函数
import decorator
@decorator.decorator
def showWaitCursor(func, *args, **kwargs):
QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
try:
return func(*args, **kwargs)
finally:
QtWidgets.QApplication.restoreOverrideCursor()
@showWaitCursor
def youFunc():
# Long process
我发现我经常需要做:
QApplication.setOverrideCursor(Qt.WaitCursor)
QApplication.ProcessEvents()
...
QApplication.restoreOverrideCursor()
然而!在 GUI 的初始化过程中,我发现由于某种原因需要进行修改:
self.ui.show() # Or your equivalent code to show the widget
QApplication.processEvents()
QApplication.setOverrideCursor(Qt.WaitCursor)
app.processEvents()
...
QApplication.restoreOverrideCursor()
否则光标不会“恢复”,直到鼠标经过修改它的小部件(如 QLineEdit),类似于@Guimute 提到的
您可以使用类 QgsTemporaryCursorOverride https://qgis.org/api/classQgsTemporaryCursorOverride.html
但是在 Python 中,您应该使用现在包含在 PyQGIS 中的 Python 上下文管理器:
from qgis.PyQt.QtCore import Qt
from qgis.utils import OverrideCursor
with OverrideCursor(Qt.WaitCursor):
do_a_slow(operation)