How can I change the cursor shape with PyQt?

2019-01-22 14:17发布

问题:

I have a simple application that runs a process that can last for several minutes before completing. So I am trying to provide an indicator to the user that it is processing the request, such as changing the cursor to an hourglass.

But I cannot quite get it to work right. All of my attempts have resulted in either an error or had no effect. And I seem to calling the cursorshapes incorrectly PyQt4.Qt.WaitCursor returns an error that the module does not contain it.

What is the correct way to indicate to the user that the process is running?

回答1:

I think QApplication.setOverrideCursor is what you're looking for:

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


回答2:

While Cameron's and David's answers are great for setting the wait cursor over an entire function, I find that a context manager works best for setting the wait cursor for snippets of code:

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()

Then put the lengthy process code in a with block:

with wait_cursor():
    # do lengthy process
    pass


回答3:

ekhumoro's solution is correct. This solution is a modification for the sake of style. I used what ekhumor's did but used a python decorator.

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

I can just put the decorator on any method I would like the spinner to be active on.

class MyWigdet(QMainWidget):

    # ...

    @waiting_effects
    def doLengthyProcess(self):
        # do lengthy process
        pass


回答4:

Better this way:

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