为什么我不能在QApplication :: notify()派生方法中使用QMessageBox

时间:2013-03-08 11:38:18

标签: qt qt4

据我了解,处理Qt中事件循环内发生的异常的方法是覆盖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" );
    }

但是当消息框出现时(即未正确呈现),该消息框为空白。我想也许这个过程没有足够的记忆。所以我尝试在开始时分配1MB内存(参见上面的m_buffer),然后在显示QMessageBox之前释放它。但这也不起作用。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

我可能会解释QApplication::notify错误,但我得到的印象是,当Qt事件循环崩溃时,您正在尝试创建GUI对象(QMessageBox)。我不相信这是可能的。

为了安全异常,我的理解是你必须使用try-catch序列包装整个QApplication :: exec函数,如the Exception Safety docs中所述。

使用qCritical和qWarning考虑implementing a custom error handler。我喜欢将这些函数重定向到临时目录中的日志文件以调试崩溃。当然,与异常处理不同,你的程序仍然崩溃,但至少你知道为什么。如有必要,我可以提供示例代码。

答案 1 :(得分:0)

静态便捷方法critical(),warning()等使用的QMessageBox :: exec()打开一个本地事件循环,只有在消息框关闭后才返回主事件循环。本地事件循环通常很讨厌,在事件处理(QApplication :: notify)中打开更是如此。您最好使用QDialog :: open打开消息框而不阻止,甚至更好地推迟消息框:

在您的申请类中:

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

不是直接调用QMessageBox :: critical(),而是用以下内容替换它:

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