2013-03-08 5 views
0

Как я понимаю, способ обработки исключений, происходящих внутри цикла событий в Qt, заключается в переопределении QApplication :: notify() и его обработке. Я попробовал это, и это работает:Почему я не могу использовать QMessageBox в методе QApplication :: notify()

class Application : public QApplication 
{ 
    Q_OBJECT 
public: 
    explicit Application(int& argc, char** argv); 

    // override to handle out of memory exceptions 
    bool notify(QObject* receiver, QEvent* e); 

signals: 

public slots: 

private: 

    char* m_buffer; 
}; 

Application::Application(int &argc, char **argv) 
    :QApplication(argc, argv) 
{ 
    m_buffer = new char[1024*1024]; 
} 

bool Application::notify(QObject *receiver, QEvent *e) 
{ 
    try 
    { 
     return QApplication::notify(receiver, e); 
    } 
    catch(std::bad_alloc&) 
    { 
     if (m_buffer) 
     { 
      delete[] m_buffer; 
      m_buffer = NULL; 
     } 

     // calling QMessageBox from here doesn't work 
     // even if release a load of reserved memory 
     // don't know why 
     QMessageBox::critical(NULL, "Exception", "Application out of memory"); 
    } 

Но окно сообщения пустое, когда она появляется (т.е. не отображается правильно). Я думал, что, возможно, этого процесса недостаточно. Поэтому я попытался выделить 1 МБ памяти в начале (см. M_buffer выше), а затем отпустил ее до отображения QMessageBox. Но это тоже не сработало. Есть идеи?

+0

Не будучи на 100% уверенным, что, когда он выходит из цикла событий QApplication, он также теряет доступ к элементам управления графическим интерфейсом. Может быть, в любом случае, я никогда не пытался переопределить ':: notify()' –

+0

Я думал об этом. Но я видел примеры кода с QMessageBox, вызываемым из Application :: notify(). –

+0

Это определенно головоломка, вы можете выделить QMessageBox на кучу? –

ответ

0

QMessageBox :: exec(), который используется статическими методами удобства критических(), warning() и т. Д., Открывает локальный цикл событий и только возвращается в цикл основного события после закрытия окна сообщения. Локальные циклы событий в целом неприятны, и открытие в середине обработки событий (QApplication :: notify) тем более. Лучше использовать QDialog :: Открыть, чтобы открыть окно сообщения без блокировки, или даже лучше, отложить окно сообщения:

В своем классе приложения:

Q_INVOKABLE void showMessage(const QString& message); // in your Application class, does the QMessageBox::critical() call 

Вместо вызова QMessageBox :: критической() напрямую заменить его на что-то вроде этого:

QMetaObject::invokeMethod(this, "showMessage", Qt::QueuedConnection, Q_ARG(QString, "Application out of memory")); 
+0

Пробовал использовать метод invoke, а затем QDialog :: open(). Все еще падает. Я думаю, после выхода из QMessageBox :: open() в вызываемом методе. –

+0

Что такое backtrace? Обязательно используйте флаг Qt :: QueuedConnection –

1

Я мог бы быть interpretting QApplication::notify неправильно, но я получаю впечатление, что вы пытаетесь создать объект GUI (QMessageBox), когда сбой цикла событий Qt. Я не думаю, что это возможно.

Для обеспечения безопасности исключений, я понимаю, что вы должны обернуть всю функцию QApplication :: exec с помощью последовательности try-catch, как в the Exception Safety docs.

Рассмотрите вопрос implementing a custom error handler с использованием qCritical и qWarning. Мне нравится перенаправлять эти функции в файл журнала в моем временном каталоге для отладки сбоев. Конечно, ваша программа по-прежнему падает, в отличие от обработки исключений, но, по крайней мере, вы знаете, почему. При необходимости я могу предоставить пример кода.

+0

Я точно знаю, почему моя программа вылетает - она ​​исчерпала всю доступную память (вычисление глубокого игрового дерева). Я просто хочу показать приятное сообщение пользователю, прежде чем я выйду, чтобы сообщить им, в чем проблема. Запись в файл журнала действительно не помогает пользователю. –

+0

Работает ли qFatal() вместо QMessageBox :: критический? – Phlucious

Смежные вопросы