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

问题描述 投票:0回答:8

我有一个简单的应用程序,它运行的进程可能会持续几分钟才能完成。我试图向用户表明它正在处理请求 - 例如将光标更改为沙漏。

但我无法让它正常工作。我的所有尝试要么导致错误,要么没有效果。我似乎错误地调用了光标形状,因为

PyQt4.Qt.WaitCursor
返回模块不包含它的错误。

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

python pyqt pyqt5 pyqt4 mouse-cursor
8个回答
69
投票

我认为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()

21
投票

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

10
投票

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

1
投票

这样更好:

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

1
投票

您可以使用类 QgsTemporaryCursorOverride https://qgis.org/api/classQgsTemporaryCursorOverride.html

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

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

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

0
投票

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

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

0
投票

我发现我经常需要做:

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 提到的


0
投票
from qtpy import QtCore, QtGui, QtWidgets

def waiting_effect(function):
    def waiting(*args, **kwargs):
        QtWidgets.QApplication.setOverrideCursor(
             QtCore.Qt.CursorShape(QtCore.Qt.CursorShape.WaitCursor)
        )
        try:
            function(*args, **kwargs)     
        finally:
            QtWidgets.QApplication.restoreOverrideCursor()

如果使用 PyQt5/PySide2,这可能有用,可以很好地处理具有多个参数的装饰函数。

© www.soinside.com 2019 - 2024. All rights reserved.