3
votes

In my MainWindow, I have a push button and a menu bar item whose signals are both connected to the same slot. In the slot function, I have written:

mainWindow->setCursor(QCursor(Qt::WaitCursor));

This works as expected when the slot function is invoked via the button; however, when the same function is invoked from the menu, the wait cursor doesn't appear. Any idea why?

I also considered using QApplication::setOverrideCursor; however, that causes other problems.

Any recommendations? Thanks!

(I am using Qt 4.7 and doing my development on Windows 7 using Qt Creator with the default MinGW compiler.)

Here's more detail.

in MainWindow constructor: this->setCursor(Qt::CrossCursor);

signal/slot connections:

QObject::connect(button, SIGNAL(clicked()), MainWindow, SLOT(showMessageBox()));  
QObject::connect(action, SIGNAL(triggered()), MainWindow, SLOT(showMessageBox())); 

showMessageBox function:

void MainWindow::showMessageBox()
{
    this->setCursor(Qt::WaitCursor);
    // display wait cursor briefly before showing message box
    for (int i = 0; i < 1<<30; ) {++i;}
    QMessageBox msgBox;
    msgBox.setText("Hello!");
    msgBox.setStandardButtons(QMessageBox::Ok);
    msgBox.setCursor(Qt::PointingHandCursor);
    msgBox.exec();
    this->setCursor(Qt::CrossCursor);
}

When showMessageBox is invoked with 'button', the wait cursor is displayed as expected.

When showMessageBox is invoked through 'action', the wait cursor does not appear; instead the cursor changes from Qt::CrossCursor to a Qt::ArrowCursor as soon as the user selects the 'action' menu item, and then changes to Qt::PointingHandCursor once the message box opens. The wait cursor never appears.

1
What are the problems using setOverrideCursor?Exa
Oh and could you post some more code? Maybe the problem is already happening in the connect macro.Exa
I expanded my post to include some sample code that reproduces the behavior. The inconvenience I found with setOverrideCursor is that if you need to show a message box at some point in a function that displays a wait cursor, then you have to temporarily remove the wait cursor (with restoreOverrideCursor); otherwise the wait cursor will also appear in the dialog box. Also, I found that you should also do the same thing when displaying a Qt-generated dialog (QFileDialog::getOpenFileName) to avoid some flicker.Jan Hettich
tried your code on my ubuntu 10.10 and it working fine: the wait cursor is displayed in both casesserge_gubenko
try using qApp->processEvents(); after you change cursor.Dmitriy

1 Answers

0
votes

Your code is synchronous and uses a delay loop. When you're in the delay loop, there's no way for any Qt code to execute. A cursor change requires the event loop to be spinning -- so it appears from the symptoms you give.

Here's how to do it correctly -- remember, if you use delays/sleeps and other blocking calls in your GUI code, your users will hate you, and rightly so. Using exec() in message/dialog boxes is also bad style. Your application is asynchronous, code it so. Make sure your slots are declared as such (in the protected slots: section of MainWindow declaration).

void MainWindow::showMessageBox()
{
    this->setCursor(Qt::WaitCursor);
    QTimer::singleSlot(200, this, SLOT(slot1()); // fire slot1 after 200ms
}

void MainWindow::slot1()
{
    QMessageBox * msgBox = new QMessageBox(this);
    msgBox->setText("Hello!");
    msgBox->setStandardButtons(QMessageBox::Ok);
    msgBox->setCursor(Qt::PointingHandCursor);
    msgBox->show();
    connect(msgBox, buttonClicked(QAbstractButton*), SLOT(slot2(QAbstractButton*)));
}

void MainWindow::slot2(QAbstractButton* button)
{
    // a button was clicked on the message box
    this->setCursor(Qt::CrossCursor);
}