PDA

View Full Version : Help! How to implement CHECK & RETURN in signal/slots



apollocheun
23rd July 2010, 08:01
I am using Qt to develop a really big software, but I got some trobule in resolving UI-Frozen-Issue in Qt framework.

For example, I have a widget named "Picture wall", which lists all the pictures in one directory, with each picture represented by a icon and a label.

After user click the icon or label, a signal will be issued and the slot on_picture_wall_item_clicked will be launched, then the picture clicked will be loaded to canvas.

If user click the items in picture wall one by one very fast, then the UI will be frozen, and the pictures clicked by user will be loaded one by one.

Of course I want the slot to CHECK whether this slot is busy (loading some other picture), if it's busy, the slot must return immediately.

My problems is that the "CHECK & RETURN" doesn't work at all. See my codes below:


void MusePictureWallWidget::on_picture_wall_item_clicke d(const QString& fileName)
{
if(!m_mutex.tryLock())
return;

if(m_busy)
return;

m_busy=true;

this->setCursor(Qt::WaitCursor);

disconnect(ui.listViewPhotoWall, SIGNAL(pictureDoubleChecked(const QString &)),this, SLOT(on_picture_wall_item_clicked(const QString&)));

this->setEnabled(false);
ui.listViewPhotoWall->setEnabled(false);
this->repaint();

QDialog dlg;
dlg.setModal(true);
dlg.show();

loadPicture(fileName);

dlg.hide();

m_busy=false;

ui.listViewPhotoWall->setEnabled(true);
this->setEnabled(true);

connect(ui.listViewPhotoWall, SIGNAL(pictureDoubleChecked(const QString &)),this, SLOT(on_picture_wall_item_clicked(const QString&)), Qt::DirectConnection);

this->unsetCursor();

m_mutex.unlock();
}

I tried 5 ways to implement the "CHECK & RETURN" in my slots.

1, QMutex, I used a mutex to lock and lock the slot, if it's occupied, the slot call should return at once.
2, An flag m_busy, the slot should then check the flag, if m_busy is true, it should return at once.
3, When a slot is launched, I disconnected this current signal/slot and reconnect them after the loading is done.
4, I raise a Modal Dialog when the slot is launched, so that the picture wall will not be clickable until the loading is done and the dialog is hiden.
5, I disable the picture wall after one slot is launched, and then enable it after loading is done.

BUT......all these did not work!!! What's wrong with my codes? How can I fix this problem? Help! Help!:rolleyes::rolleyes:

Ginsengelf
23rd July 2010, 08:29
Hi, I think at least the mutex approach should work, but you have to be more specific on how "it does not work". For example, does the tryLock() call fail sometimes?

On another note, I would expect the program to display the item I clicked last, and not the one it is still working on. So in my opinion it would be better to abort a running loading operation at restart with the newly clicked item.

Ginsengelf

apollocheun
23rd July 2010, 08:37
Hi, I think at least the mutex approach should work, but you have to be more specific on how "it does not work". For example, does the tryLock() call fail sometimes?

On another note, I would expect the program to display the item I clicked last, and not the one it is still working on. So in my opinion it would be better to abort a running loading operation at restart with the newly clicked item.

Ginsengelf

Thank you Ginsengelf, you are right. I also expect the program to display the last clicked, but terminating a loading process is not easy and not safe sometime.

I guess, QObject won't issue another signal until the first signal has been proceeded? Am I right?

wysota
23rd July 2010, 09:42
I would suggest to read this article: Keeping the GUI Responsive. QtConcurrent seems to be a perfect solution for your problem.

Your mutex approach is useless because only one thread tries to access the mutex so it will never block on it. It's much better to do the work in another thread and only when the picture is ready, display it on your wall. It then doesn't even matter if the user clicks 1 image or 100, because they will be loaded one after the other and all without blocking the UI. It's just a matter of which one you display.

Ginsengelf
23rd July 2010, 09:51
Your mutex approach is useless because only one thread tries to access the mutex so it will never block on it.
You're right of course. At the moment I see threads lurking at every corner...