Python 如何使用PyQt更改光标形状?

Python 如何使用PyQt更改光标形状?,python,pyqt,cursor,pyqt5,pyqt4,Python,Pyqt,Cursor,Pyqt5,Pyqt4,我有一个简单的应用程序,它运行一个进程,在完成之前可以持续几分钟。我试图向用户提供一个它正在处理请求的指示,例如将光标更改为沙漏 但我不能让它正常工作。我所有的尝试都导致了错误或无效。我似乎错误地调用了游标形状,因为PyQt4.Qt.WaitCursor返回一个错误,即模块不包含它 向用户指示进程正在运行的正确方式是什么?我想这就是您要寻找的: PyQt5: from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QApplication

我有一个简单的应用程序,它运行一个进程,在完成之前可以持续几分钟。我试图向用户提供一个它正在处理请求的指示,例如将光标更改为沙漏

但我不能让它正常工作。我所有的尝试都导致了错误或无效。我似乎错误地调用了游标形状,因为
PyQt4.Qt.WaitCursor
返回一个错误,即模块不包含它

向用户指示进程正在运行的正确方式是什么?

我想这就是您要寻找的:

PyQt5

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication
...
QApplication.setOverrideCursor(Qt.WaitCursor)
# do lengthy process
QApplication.restoreOverrideCursor()
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QApplication
...
QApplication.setOverrideCursor(Qt.WaitCursor)
# do lengthy process
QApplication.restoreOverrideCursor()
PyQt4

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication
...
QApplication.setOverrideCursor(Qt.WaitCursor)
# do lengthy process
QApplication.restoreOverrideCursor()
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QApplication
...
QApplication.setOverrideCursor(Qt.WaitCursor)
# do lengthy process
QApplication.restoreOverrideCursor()

Ekhumaro的解决方案是正确的。此解决方案是为了风格而进行的修改。我使用了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

虽然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

根据我的说法,添加光标的最佳方法是使用装饰器。通过这种方式,您可以运行任何函数,只需将光标作为装饰器添加到该函数中即可

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),类似于@Guimoute提到的,您可以使用类QgsTemporaryCursorOverride

但是在Python中,您应该使用Python上下文管理器,它现在包含在PyQGIS中:

from qgis.PyQt.QtCore import Qt
from qgis.utils import OverrideCursor

with OverrideCursor(Qt.WaitCursor):
    do_a_slow(operation)

装饰师是个好主意,谢谢。我建议调用
函数(*args,**kwargs)
,返回
函数的返回值,并将其调用包装在
try…finally
块中,以获得更多的好处。我似乎无法在这条评论中说明这一点,因此接下来我将尝试编辑您的解决方案。将try块更改为
返回函数(*args,**kwargs)
可能也很有用,或者至少在我的情况下是这样。注意:这在PyQt4中有效。然而,Linux(Ubuntu16.10)下的PySide1.2.2说“X错误:BadCursor(无效的游标参数)6”“主要操作码:2(X_ChangeWindowAttributes)”“资源id:0xa”。将PySide的setOverrideCursor(Qt.WaitCursor)而不是setOverrideCursor(QCursor(Qt.WaitCursor))馈送到PySide的setOverrideCursor(Qt.WaitCursor))是可行的——尽管文档中说需要QCursor()。在某些情况下,还原也会出现类似的错误。这似乎是一个已知的PySide错误。@Ubuntourist。谢谢-我可以确认PySide中的错误。
QCursor
类有一个复制构造函数,它接受
Qt.CursorShape
enum值,因此实际上不需要使用
QCursor
本身。我认为在Qt端创建
QCursor
是修复PySide问题的方法。出于某种原因,这个解决方案在PyQt5中对我有效,但恢复常规光标(alt+tab,或者像任何输入小部件一样移动其他小部件,也会改变光标)需要失去焦点
QApplication.restoreOverrideCursor()
如果我不移动,单独使用将不会起任何作用。@Guimoute您应该发布一个关于这方面的新问题,并提供一个解决方案。这是最简单、最优雅和通用的解决方案