Blocking custom events from being processed
-
Hi all,
Problem:
- In a custom event handler I detect bad data.
- I open a QMessageBox to inform the user (ignore,abort)
- During QMessageBox.exec(), an other CustomEvent (already sent) is being processed too. Unfortunatly the handler of the second event deletes data, which I depend on, while handling the first event.
- When the user decides to continue (Ignore Button) my application is crashing, because a pointer isn't valid anymore.
Question:
Is there a simple possibility to tell the application, not to process some kind of events ?Somthing like:
@QCoreApplication::blockEvents( MyCustomType);
messageBox.exec();
QCoreApplication::unblockEvents( MyCustomType);@thanks a lot for any hints ore ideas
Nik -
Hello,
Not sure what's going on in your second event handler but how your tried the event filter?
Some primitive way might be by using the event filters:
@
//void QObject::installEventFilter ( QObject *filter )
messageBox.exec();
//void QObject::removeEventFilter ( QObject *filter )
@Not sure if this is what you need but check the "QObject::installEventFilter":http://qt-project.org/doc/qt-4.8/qobject.html#installEventFilter
-
Thanks gmaro for answering
I was thinking about EventFilter too, but its not exactly what i need. The EvenFilter doesn't prevent events from being processed, it's just a "mixed in" EventHandler. But I want to process the events later, after closing QMessageBox.
Ok, the EventFilter could store the events, to send them back to the Application again after closing QMessageBox.
Using Windows MessageBox instead of QMessageBox would solve the problem. But for the moment I don't consider this as a solution.
I just can't belive that Qt doesn't provide an easy technic for this problem.
-
If I understand what you're getting at, wouldn't a QMutex + QMutexLocker do the trick? You're trying to block all successive events until after the first has finished, yes?
-
Yes, I want to block all events not addressing the QMessageBox instance, thats right.
I dont't see how you can achieve that with a QMutext?
-
That is exaxtly what mutexes are designed for: once a lock is placed on a mutex, anything else which tries to lock that same mutex will block until the first lock is lifted.
So, lock the mutex every time you handle a custom event. It will wait until any already started custom events have been processed before starting a new one.
-
Your solution results in dead lock, because the MouseEvent handling for the QMessageBox is locked too.
-
qnik, do you think you can share a bit more from your solution. Maybe we can change the way of creation of events that are dispatched in your custom event handler and causes the deletion problem.
In general I think it would be good to know - what is creating events that you want to "hold" for message box processing time, and what does your custom event handler.
-
simplified it's somthing like:
@
void Widget::mousePressEvent ( QMouseEvent * event ){
QCoreApplication::postEvent( mainWin, new MyEvent1);
QCoreApplication::postEvent( mainWin, new MyEvent1);
}void MainWindow::customEvent ( QEvent * pEvent ){
switch( pEvent->type()){
case MyEvent1:
handleEvent1( pEvent);
break;
}void MainWindow::handleEvent1( QEvent * pEvent)
{
Data p = * Manager::create( pEvent);
try{
doSomthing( p);
}catch( x& e){
QMessageBox msg;
mbox.setText( e.what());
int ret = msg.exec();
if( ret == QMessageBox::Abort){
return
}doSomthingElse( p);
}
}
@ -
The solution with the event filter works (see code below), allthough I don't like it very much:
@
class CustomEventBlocker : public QObject
{
typedef QPair<QObject*, QEvent*> tEvnt;
typedef QList<tEvnt> tEventStore;
tEventStore m_EventStore;protected:
bool eventFilter(QObject *obj, QEvent *pEvnt){
switch( pEvnt->type()){ case Event::Types::PageOpen: pEvnt = new Event::PageOpen( *static_cast<Event::PageOpen*>(pEvnt)); break; default: return QObject::eventFilter(obj, pEvnt); } // store event, post later again m_EventStore.append( tEvnt( obj,pEvnt) ); return true;
}
public:
CustomEventBlocker()
:QObject()
{
Epam::getInstance().getMainWidget()->installEventFilter( this);
}~CustomEventBlocker()
{
Epam::getInstance().getMainWidget()->removeEventFilter( this);// post stored events
tEventStore::iterator iEnd = m_EventStore.end();
for( tEventStore::iterator itor = m_EventStore.begin(); itor != iEnd; ++itor){
QCoreApplication::postEvent( itor->first, itor->second);
}
}
};//------------------------
int ret = 0;
{
CustomEventBlocker customEventBlocker;
ret = mbox.exec();
}
@