Qt C ++ QException问题:调试错误 [英] Qt C++ QException issue : debug error

查看:336
本文介绍了Qt C ++ QException问题:调试错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从XML文件中读取对象,我需要处理2个异常:当文件无法打开,以及无法加载文件内容时。 (不正确地形成)我写了以下函数来读取文件中的内容和2个clases的异常。问题是,当我运行我的应用程序,我试图加载一个不同格式的文件,然后XML,而不是一个frindly消息,通知有一个异常,我有一个调试错误:abort()被调用。我做得不好吗?
读取功能

I want to read objects from an XML file and i need to handle 2 exceptions : when the file cannot be opened and when the file content cannot be loaded. (incorrectly formated) I have written the following function to read the content from the file and 2 clases for the exceptions. The problem is that when i run my application and i am trying to load a file with different format then XML, instead of a frindly message which informs that there is an exception, i have a debug error : abort() is called. What i am not doing well? reading function

QList<Vehicle> VehicleHelper::readVehicles(QString fileName){
QList<Vehicle> vehicles;
Vehicle newVehicle;
QFile file(fileName);
QDomDocument document;
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
    throw FileCannotBeOpenException();
}
else{
    if(!document.setContent(&file)){
        throw InvalidXMLContentException();
    }
    file.close();
}

QDomElement root = document.firstChildElement();
QDomNodeList carElements = root.elementsByTagName("Car");
for(int i = 0; i < carElements.size(); i++){

    QDomNode carNode = carElements.at(i);

    QDomElement carElement = carNode.toElement();
    QString carID = carElement.attribute("ID");

    //if the idNumber is null, generate one
    if(carID.isEmpty()){
        QUuid newId = Vehicle::generateID();
        newVehicle.setVehicleId(newId);
    }
    else {
        QUuid id;
        try{
            id = QUuid::QUuid(carID);
        } catch(QException &ex){
            continue;
        }


        newVehicle.setVehicleId(id);
    }
  }

函数的调用

void MainWindow::on_actionOpen_triggered()
{
if(isModified){
    QMessageBox msgBox;
    QString message = "There are unsaved changes! Do you proceed? ";
    msgBox.setWindowTitle("Save Changes");
    msgBox.setText(message);
    msgBox.addButton("Don't save",QMessageBox::NoRole);
    msgBox.addButton(QMessageBox::Save);
    msgBox.addButton(QMessageBox::Cancel);
    msgBox.setIcon(QMessageBox::Question);
    int result = msgBox.exec();
    if(result == QMessageBox::Save){
        VehicleHelper::writeVehicles(cars,filename);
        msgBox.close();
    } else {
        QString fileName = QFileDialog::getOpenFileName(this,"Open file");
        if(!fileName.isEmpty()){
            setFileName(fileName);
            QFile file(fileName);
            try {
                cars = VehicleHelper::readVehicles(fileName);
            } catch(FileCannotBeOpenException &ex) {
                QMessageBox msgBox;
                msgBox.setIcon(QMessageBox::Critical);
                msgBox.setWindowTitle("Message!");
                msgBox.setText("Failed to open file");
                msgBox.setDefaultButton(QMessageBox::Ok);
                msgBox.exec();
                return;

            } catch(InvalidXMLContentException &ex){
                QMessageBox msgBox;
                msgBox.setIcon(QMessageBox::Critical);
                msgBox.setWindowTitle("Message!");
                msgBox.setText("Failed to load data!");
                msgBox.setDefaultButton(QMessageBox::Ok);
                msgBox.exec();
                return;
            }

            setTakenNumbersList(cars);
            //set data to the table view
            populate(cars);
       }
    }
 } else {
    QString fileName = QFileDialog::getOpenFileName(this,"Open file");
    if(!fileName.isEmpty()){
        setFileName(fileName);
        QFile file(fileName);
        if(file.open(QFile::ReadOnly | QFile::Text)){
            cars = VehicleHelper::readVehicles(fileName);
            setTakenNumbersList(cars);
            file.close();

            //set data to the table view
            populate(cars);

            ui->actionAdd->setEnabled(true);
            ui->actionBy_name->setEnabled(true);
            ui->actionBy_registration_date->setEnabled(true);
            ui->actionBy_registration_number->setEnabled(true);
            ui->actionBy_revision_date->setEnabled(true);
            ui->actionBy_type->setEnabled(true);
            ui->actionClear_Search->setEnabled(true);
            ui->actionDelete->setEnabled(true);
            ui->actionEdit->setEnabled(true);
            ui->actionSave->setEnabled(true);
            ui->actionSave_As->setEnabled(true);
        }
     }

    }
 }

main

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
try{
    w.show();
} catch(QException &ex){

}
return a.exec();
}


推荐答案

在事件循环中运行,具体而言,它们将到达 QCoreApplication :: notify()。通过中间操作系统事件循环调用,从 a.exec()间接调用此方法。

The exceptions are thrown from code that runs in the event loop, specifically they will reach the QCoreApplication::notify(). This one is indirectly called from a.exec(), via an intervening operating system event loop call.

你不能只是在try / catch中包装 a.exec()。您必须按如下方式重新实现 QCoreApplication :: notify()

Thus you can't merely wrap a.exec() in a try/catch. You must reimplement QCoreApplication::notify() as follows:

class MyApplication : public QApplication
{
public:
   MyApplication(int & c, char ** a) : QApplication(c,a) {}
   virtual bool notify(QObject * obj, QEvent * ev) {
      bool rc = true;
      try {
         rc = QApplication::notify(obj, ev);
      }
      catch (QException &ex) {
         ...
      }
      return rc;
   }
};

int main(...) {
   MyApplication app(...);
   ...
}

您的代码的另一个问题是它尖叫以使用状态机框架。您应该具有表示文件被打开和关闭的状态,以及中间状态。将显示未保存的更改对话框。然后你不会在代码周围有 ui-> actionXYZ-> setEnabled(true)。假设你有一个 fileOpen 状态,你会有

Another problem with your code is that it screams to use the State Machine Framework. You should have states that represent file being open and closed, and intermediate states when e.g. an "unsaved changes" dialog box is shown. Then you won't have the ui->actionXYZ->setEnabled(true) littered around the code. Assuming you have a fileOpen state, you'd have

fileOpen->assignProperty(ui->actionBy_name, "setEnabled", true);
...

然后当文件打开时,发出一个附加的信号到状态机中的信号转换。状态机将执行其余操作 - 它将为您启用/禁用操作等。

Then when the file is open, you emit a signal that is attached to a signal transition in the state machine. The state machine will do the rest - it will enable/disable actions for you, etc.

这篇关于Qt C ++ QException问题:调试错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆